diff options
Diffstat (limited to 'src')
516 files changed, 29651 insertions, 14226 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8c8b9e0126f..fe367ba22d0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory(framework) add_subdirectory(shared) -add_subdirectory(trinityrealm) +add_subdirectory(realmd) add_subdirectory(game) add_subdirectory(bindings) -add_subdirectory(trinitycore) +add_subdirectory(mangosd) diff --git a/src/Makefile.am b/src/Makefile.am index 40787fa17d0..7309b10db83 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> # -# Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> +# Thanks to the original authors: MaNGOS <http://getmangos.com/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -9,17 +9,17 @@ # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Process this file with automake to produce Makefile.in ## Sub-directories to parse -SUBDIRS = framework shared trinityrealm game bindings trinitycore +SUBDIRS = tools framework shared realmd game bindings mangosd ## Additional files to include when running 'make dist' # Nothing yet. diff --git a/src/bindings/Makefile.am b/src/bindings/Makefile.am index 5e85dfe15bc..26914e8fde1 100644 --- a/src/bindings/Makefile.am +++ b/src/bindings/Makefile.am @@ -1,6 +1,6 @@ -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> # -# Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> +# Thanks to the original authors: MaNGOS <http://getmangos.com/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,8 +18,8 @@ # interface folder is disabled for now -if USE_TSCRIPTS +#if USE_TSCRIPTS SUBDIRS = scripts -else -SUBDIRS = interface -endif +#else +#SUBDIRS = interface +#endif diff --git a/src/bindings/interface/Makefile.am b/src/bindings/interface/Makefile.am index bcca2128203..9bb53f98454 100644 --- a/src/bindings/interface/Makefile.am +++ b/src/bindings/interface/Makefile.am @@ -1,6 +1,6 @@ -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> # -# Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> +# Thanks to the original authors: MaNGOS <http://getmangos.com/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/src/bindings/interface/ScriptMgr.cpp b/src/bindings/interface/ScriptMgr.cpp index 276b5fa3a54..abbde65c51a 100644 --- a/src/bindings/interface/ScriptMgr.cpp +++ b/src/bindings/interface/ScriptMgr.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * - * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> + * Thanks to the original authors: MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/bindings/interface/ScriptMgr.h b/src/bindings/interface/ScriptMgr.h index 30d94ac01e1..2296d2247de 100644 --- a/src/bindings/interface/ScriptMgr.h +++ b/src/bindings/interface/ScriptMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * - * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> + * Thanks to the original authors: MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/bindings/interface/Scripts/sc_default.cpp b/src/bindings/interface/Scripts/sc_default.cpp index 79796eba8f6..f6c8386579f 100644 --- a/src/bindings/interface/Scripts/sc_default.cpp +++ b/src/bindings/interface/Scripts/sc_default.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * - * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> + * Thanks to the original authors: MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/bindings/interface/Scripts/sc_defines.cpp b/src/bindings/interface/Scripts/sc_defines.cpp index 2c7c4ec743f..45456a1d5e2 100644 --- a/src/bindings/interface/Scripts/sc_defines.cpp +++ b/src/bindings/interface/Scripts/sc_defines.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * - * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> + * Thanks to the original authors: MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/bindings/interface/Scripts/sc_defines.h b/src/bindings/interface/Scripts/sc_defines.h index 1f8b468dc05..ecd55aa7282 100644 --- a/src/bindings/interface/Scripts/sc_defines.h +++ b/src/bindings/interface/Scripts/sc_defines.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * - * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> + * Thanks to the original authors: MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/bindings/interface/config.h b/src/bindings/interface/config.h index f074f0a3351..ab312d7d3f4 100644 --- a/src/bindings/interface/config.h +++ b/src/bindings/interface/config.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * - * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> + * Thanks to the original authors: MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/bindings/interface/system.cpp b/src/bindings/interface/system.cpp index 3c76284b5af..20eaf9ce64c 100644 --- a/src/bindings/interface/system.cpp +++ b/src/bindings/interface/system.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * - * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> + * Thanks to the original authors: MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/bindings/scripts/CMakeLists.txt b/src/bindings/scripts/CMakeLists.txt index d908064ca9b..e482940a280 100644 --- a/src/bindings/scripts/CMakeLists.txt +++ b/src/bindings/scripts/CMakeLists.txt @@ -106,6 +106,7 @@ SET(trinityscript_LIB_SRCS scripts/zone/blasted_lands/blasted_lands.cpp scripts/zone/blasted_lands/boss_kruul.cpp scripts/zone/bloodmyst_isle/bloodmyst_isle.cpp + scripts/zone/borean_tundra/borean_tundra.cpp scripts/zone/burning_steppes/burning_steppes.cpp scripts/zone/caverns_of_time/dark_portal/def_dark_portal.h scripts/zone/caverns_of_time/dark_portal/instance_dark_portal.cpp @@ -346,6 +347,8 @@ SET(trinityscript_LIB_SRCS scripts/zone/uldaman/uldaman.cpp scripts/zone/undercity/undercity.cpp scripts/zone/ungoro_crater/ungoro_crater.cpp + scripts/zone/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp + scripts/zone/utgarde_keep/utgarde_keep/boss_keleseth.cpp scripts/zone/wailing_caverns/instance_wailing_caverns.cpp scripts/zone/western_plaguelands/western_plaguelands.cpp scripts/zone/westfall/westfall.cpp diff --git a/src/bindings/scripts/Makefile.am b/src/bindings/scripts/Makefile.am index ac5965336a6..0e1890ac869 100644 --- a/src/bindings/scripts/Makefile.am +++ b/src/bindings/scripts/Makefile.am @@ -1,6 +1,6 @@ -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> # -# Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> +# Thanks to the original authors: MaNGOS <http://getmangos.com/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -140,6 +140,7 @@ scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp \ scripts/zone/blasted_lands/blasted_lands.cpp \ scripts/zone/blasted_lands/boss_kruul.cpp \ scripts/zone/bloodmyst_isle/bloodmyst_isle.cpp \ +scripts/zone/borean_tundra/borean_tundra.cpp \ scripts/zone/burning_steppes/burning_steppes.cpp \ scripts/zone/caverns_of_time/dark_portal/boss_aeonus.cpp \ scripts/zone/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp \ @@ -379,6 +380,8 @@ scripts/zone/uldaman/boss_ironaya.cpp \ scripts/zone/uldaman/uldaman.cpp \ scripts/zone/undercity/undercity.cpp \ scripts/zone/ungoro_crater/ungoro_crater.cpp \ +scripts/zone/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp \ +scripts/zone/utgarde_keep/utgarde_keep/boss_keleseth.cpp \ scripts/zone/wailing_caverns/instance_wailing_caverns.cpp \ scripts/zone/western_plaguelands/western_plaguelands.cpp \ scripts/zone/westfall/westfall.cpp \ diff --git a/src/bindings/scripts/ScriptMgr.cpp b/src/bindings/scripts/ScriptMgr.cpp index c41a461e4d1..5dc16953860 100644 --- a/src/bindings/scripts/ScriptMgr.cpp +++ b/src/bindings/scripts/ScriptMgr.cpp @@ -211,6 +211,9 @@ extern void AddSC_blasted_lands(); //Bloodmyst Isle extern void AddSC_bloodmyst_isle(); +//Borean Tundra +extern void AddSC_borean_tundra(); + //Burning steppes extern void AddSC_burning_steppes(); @@ -392,12 +395,12 @@ extern void AddSC_boss_patchwerk(); extern void AddSC_boss_razuvious(); extern void AddSC_boss_highlord_mograine(); extern void AddSC_boss_kelthuzad(); -extern void AddSC_boss_faerlina(); extern void AddSC_boss_loatheb(); extern void AddSC_boss_noth(); extern void AddSC_boss_gluth(); extern void AddSC_boss_sapphiron(); extern void AddSC_boss_four_horsemen(); +extern void AddSC_boss_faerlina(); //Netherstorm extern void AddSC_netherstorm(); @@ -566,6 +569,11 @@ extern void AddSC_undercity(); extern void AddSC_ungoro_crater(); //Upper blackrock spire + +//Utgarde Keep +extern void AddSC_boss_keleseth(); +extern void AddSC_instance_utgarde_keep(); + //Wailing caverns //Western plaguelands @@ -1418,6 +1426,9 @@ void ScriptsInit() //Bloodmyst Isle AddSC_bloodmyst_isle(); + + //Borean Tundra + AddSC_borean_tundra(); //Burning steppes AddSC_burning_steppes(); @@ -1594,12 +1605,12 @@ void ScriptsInit() //Naxxramas AddSC_boss_anubrekhan(); + AddSC_boss_faerlina(); AddSC_boss_maexxna(); AddSC_boss_patchwerk(); AddSC_boss_razuvious(); - AddSC_boss_highlord_mograine(); - AddSC_boss_kelthuzad(); - AddSC_boss_faerlina(); + AddSC_boss_highlord_mograine(); + AddSC_boss_kelthuzad(); AddSC_boss_loatheb(); AddSC_boss_noth(); AddSC_boss_gluth(); @@ -1773,6 +1784,11 @@ void ScriptsInit() AddSC_ungoro_crater(); //Upper blackrock spire + + //Utgarde Keep + AddSC_boss_keleseth(); + AddSC_instance_utgarde_keep(); + //Wailing caverns //Western plaguelands diff --git a/src/bindings/scripts/ScriptMgr.h b/src/bindings/scripts/ScriptMgr.h index ef7bdfd3cce..ebc102f32d9 100644 --- a/src/bindings/scripts/ScriptMgr.h +++ b/src/bindings/scripts/ScriptMgr.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +/* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * Thanks to the original authors: ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * diff --git a/src/bindings/scripts/VC71/71ScriptDev2.vcproj b/src/bindings/scripts/VC71/71ScriptDev2.vcproj index a309f585589..302d97c9736 100644 --- a/src/bindings/scripts/VC71/71ScriptDev2.vcproj +++ b/src/bindings/scripts/VC71/71ScriptDev2.vcproj @@ -1879,6 +1879,7 @@ RelativePath="..\scripts\zone\caverns_of_time\dark_portal\instance_dark_portal.cpp" > </File> + </Filter> <Filter Name="Battle for Mt. Hyjal" @@ -1936,6 +1937,9 @@ > </File> </Filter> + <Filter + Name="Culling of Stratholme"> + </Filter> </Filter> <Filter Name="Silvermoon City" @@ -1969,6 +1973,107 @@ > </File> </Filter> + <Filter + Name="Borean Tundra"> + <File + RelativePath="..\scripts\zone\borean_tundra\borean_tundra.cpp" + > + </File> + </Filter> + <Filter + Name="Howling Fjord"> + </Filter> + <Filter + Name="Crystalsong Forest"> + </Filter> + <Filter + Name="Dalaran"> + </Filter> + <Filter + Name="Dragonblight"> + </Filter> + <Filter + Name="Grizzly Hills"> + </Filter> + <Filter + Name="Icecrown"> + </Filter> + <Filter + Name="Sholazar Basin"> + </Filter> + <Filter + Name="The Storm Peaks"> + </Filter> + <Filter + Name="Zul'Drak"> + </Filter> + <Filter + Name="Azjol-Nerub"> + <Filter + Name="Ahn'kahet"> + </Filter> + <Filter + Name="Azjol-Nerub"> + </Filter> + </Filter> + <Filter + Name="Drak'Tharon Keep"> + </Filter> + <Filter + Name="Gundrak"> + </Filter> + <Filter + Name="Nexus"> + <Filter + Name="Nexus"> + </Filter> + <Filter + Name="Oculus"> + </Filter> + <Filter + Name="Eye of Eternity"> + </Filter> + </Filter> + <Filter + Name="Violet Hold"> + </Filter> + <Filter + Name="Ulduar" + > + <Filter + Name="Halls of Stone"> + </Filter> + <Filter + Name="Halls of Lightning"> + </Filter> + </Filter> + <Filter + Name="Utgarde Keep"> + <Filter + Name="Utgarde Keep"> + <File + RelativePath="..\scripts\zone\utgarde_keep\utgarde_keep\boss_keleseth.cpp" + > + </File> + <File + RelativePath="..\scripts\zone\utgarde_keep\utgarde_keep\def_keep.h" + > + </File> + <File + RelativePath="..\scripts\zone\utgarde_keep\utgarde_keep\instance_utgarde_keep.cpp" + > + </File> + </Filter> + <Filter + Name="Utgarde Pinnacle"> + </Filter> + </Filter> + <Filter + Name="Obsidian Sanctum"> + </Filter> + <Filter + Name="Vault of Archavon"> + </Filter> <Filter Name="Shattrath City" > diff --git a/src/bindings/scripts/VC80/80ScriptDev2.vcproj b/src/bindings/scripts/VC80/80ScriptDev2.vcproj index e4e20bbb129..62fa4d240e6 100644 --- a/src/bindings/scripts/VC80/80ScriptDev2.vcproj +++ b/src/bindings/scripts/VC80/80ScriptDev2.vcproj @@ -1078,6 +1078,107 @@ Name="Ragefire Chasm" > </Filter> + <Filter + Name="Borean Tundra"> + <File + RelativePath="..\scripts\zone\borean_tundra\borean_tundra.cpp" + > + </File> + </Filter> + <Filter + Name="Howling Fjord"> + </Filter> + <Filter + Name="Crystalsong Forest"> + </Filter> + <Filter + Name="Dalaran"> + </Filter> + <Filter + Name="Dragonblight"> + </Filter> + <Filter + Name="Grizzly Hills"> + </Filter> + <Filter + Name="Icecrown"> + </Filter> + <Filter + Name="Sholazar Basin"> + </Filter> + <Filter + Name="The Storm Peaks"> + </Filter> + <Filter + Name="Zul'Drak"> + </Filter> + <Filter + Name="Azjol-Nerub"> + <Filter + Name="Ahn'kahet"> + </Filter> + <Filter + Name="Azjol-Nerub"> + </Filter> + </Filter> + <Filter + Name="Drak'Tharon Keep"> + </Filter> + <Filter + Name="Gundrak"> + </Filter> + <Filter + Name="Nexus"> + <Filter + Name="Nexus"> + </Filter> + <Filter + Name="Oculus"> + </Filter> + <Filter + Name="Eye of Eternity"> + </Filter> + </Filter> + <Filter + Name="Violet Hold"> + </Filter> + <Filter + Name="Ulduar" + > + <Filter + Name="Halls of Stone"> + </Filter> + <Filter + Name="Halls of Lightning"> + </Filter> + </Filter> + <Filter + Name="Utgarde Keep"> + <Filter + Name="Utgarde Keep"> + <File + RelativePath="..\scripts\zone\utgarde_keep\utgarde_keep\boss_keleseth.cpp" + > + </File> + <File + RelativePath="..\scripts\zone\utgarde_keep\utgarde_keep\def_keep.h" + > + </File> + <File + RelativePath="..\scripts\zone\utgarde_keep\utgarde_keep\instance_utgarde_keep.cpp" + > + </File> + </Filter> + <Filter + Name="Utgarde Pinnacle"> + </Filter> + </Filter> + <Filter + Name="Obsidian Sanctum"> + </Filter> + <Filter + Name="Vault of Archavon"> + </Filter> <Filter Name="Razorfen Downs" > @@ -2086,6 +2187,9 @@ </File> </Filter> <Filter + Name="Culling of Stratholme"> + </Filter> + <Filter Name="Old Hillsbrad" > <File diff --git a/src/bindings/scripts/VC90/90ScriptDev2.vcproj b/src/bindings/scripts/VC90/90ScriptDev2.vcproj index e6d36179274..dfb4b147848 100644 --- a/src/bindings/scripts/VC90/90ScriptDev2.vcproj +++ b/src/bindings/scripts/VC90/90ScriptDev2.vcproj @@ -748,6 +748,134 @@ > </Filter> <Filter + Name="Borean Tundra" + > + <File + RelativePath="..\scripts\zone\borean_tundra\borean_tundra.cpp" + > + </File> + </Filter> + <Filter + Name="Howling Fjord" + > + </Filter> + <Filter + Name="Crystalsong Forest" + > + </Filter> + <Filter + Name="Dalaran" + > + </Filter> + <Filter + Name="Dragonblight" + > + </Filter> + <Filter + Name="Grizzly Hills" + > + </Filter> + <Filter + Name="Icecrown" + > + </Filter> + <Filter + Name="Sholazar Basin" + > + </Filter> + <Filter + Name="The Storm Peaks" + > + </Filter> + <Filter + Name="Zul'Drak" + > + </Filter> + <Filter + Name="Azjol-Nerub" + > + <Filter + Name="Ahn'kahet" + > + </Filter> + <Filter + Name="Azjol-Nerub" + > + </Filter> + </Filter> + <Filter + Name="Drak'Tharon Keep" + > + </Filter> + <Filter + Name="Gundrak" + > + </Filter> + <Filter + Name="Nexus" + > + <Filter + Name="Nexus" + > + </Filter> + <Filter + Name="Oculus" + > + </Filter> + <Filter + Name="Eye of Eternity" + > + </Filter> + </Filter> + <Filter + Name="Violet Hold" + > + </Filter> + <Filter + Name="Ulduar" + > + <Filter + Name="Halls of Stone" + > + </Filter> + <Filter + Name="Halls of Lightning" + > + </Filter> + </Filter> + <Filter + Name="Utgarde Keep" + > + <Filter + Name="Utgarde Keep" + > + <File + RelativePath="..\scripts\zone\utgarde_keep\utgarde_keep\boss_keleseth.cpp" + > + </File> + <File + RelativePath="..\scripts\zone\utgarde_keep\utgarde_keep\def_keep.h" + > + </File> + <File + RelativePath="..\scripts\zone\utgarde_keep\utgarde_keep\instance_utgarde_keep.cpp" + > + </File> + </Filter> + <Filter + Name="Utgarde Pinnacle" + > + </Filter> + </Filter> + <Filter + Name="Obsidian Sanctum" + > + </Filter> + <Filter + Name="Vault of Archavon" + > + </Filter> + <Filter Name="Scarlet Monastery" > <File @@ -2079,6 +2207,10 @@ </File> </Filter> <Filter + Name="Culling of Stratholme" + > + </Filter> + <Filter Name="Old Hillsbrad" > <File diff --git a/src/bindings/scripts/include/sc_creature.cpp b/src/bindings/scripts/include/sc_creature.cpp index 6c9a0059b11..8764f612557 100644 --- a/src/bindings/scripts/include/sc_creature.cpp +++ b/src/bindings/scripts/include/sc_creature.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +/* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * Thanks to the original authors: ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * @@ -454,11 +454,9 @@ SpellEntry const* ScriptedAI::SelectSpell(Unit* Target, int32 School, int32 Mech return false; //Using the extended script system we first create a list of viable spells - SpellEntry const* Spell[4]; - Spell[0] = 0; - Spell[1] = 0; - Spell[2] = 0; - Spell[3] = 0; + SpellEntry const* Spell[CREATURE_MAX_SPELLS]; + for (uint8 i=0;i<CREATURE_MAX_SPELLS;i++) + Spell[i] = 0; uint32 SpellCount = 0; @@ -466,7 +464,7 @@ SpellEntry const* ScriptedAI::SelectSpell(Unit* Target, int32 School, int32 Mech SpellRangeEntry const* TempRange; //Check if each spell is viable(set it to null if not) - for (uint32 i = 0; i < 4; i++) + for (uint32 i = 0; i < CREATURE_MAX_SPELLS; i++) { TempSpell = GetSpellStore()->LookupEntry(m_creature->m_spells[i]); @@ -600,7 +598,7 @@ void FillSpellSummary() //Spell targets AoE at enemy if ( TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_CASTER || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1); @@ -609,7 +607,7 @@ void FillSpellSummary() TempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER || + TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_CASTER || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED ) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1); @@ -622,7 +620,7 @@ void FillSpellSummary() //Spell targets aoe friends if ( TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER || TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER) + TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1); //Spell targets any friend(or self) @@ -631,7 +629,7 @@ void FillSpellSummary() TempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY || TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER || TempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY || - TempSpell->EffectImplicitTargetA[j] == TARGET_ALL_AROUND_CASTER) + TempSpell->EffectImplicitTargetA[j] == TARGET_DEST_CASTER) SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1); //Make sure that this spell includes a damage effect @@ -752,7 +750,7 @@ Unit* FindCreature(uint32 entry, float range, Unit* Finder) return NULL; Creature* target = NULL; Trinity::AllCreaturesOfEntryInRange check(Finder, entry, range); - Trinity::CreatureSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(target, check); + Trinity::CreatureSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(Finder, target, check); Finder->VisitNearbyObject(range, searcher); return target; } @@ -763,7 +761,7 @@ GameObject* FindGameObject(uint32 entry, float range, Unit* Finder) return NULL; GameObject* target = NULL; Trinity::AllGameObjectsWithEntryInGrid go_check(entry); - Trinity::GameObjectSearcher<Trinity::AllGameObjectsWithEntryInGrid> searcher(target, go_check); + Trinity::GameObjectSearcher<Trinity::AllGameObjectsWithEntryInGrid> searcher(Finder, target, go_check); Finder->VisitNearbyGridObject(range, searcher); return target; } @@ -772,7 +770,7 @@ Unit* ScriptedAI::DoSelectLowestHpFriendly(float range, uint32 MinHPDiff) { Unit* pUnit = NULL; Trinity::MostHPMissingInRange u_check(m_creature, range, MinHPDiff); - Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange> searcher(pUnit, u_check); + Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange> searcher(m_creature, pUnit, u_check); m_creature->VisitNearbyObject(range, searcher); return pUnit; } @@ -781,7 +779,7 @@ std::list<Creature*> ScriptedAI::DoFindFriendlyCC(float range) { std::list<Creature*> pList; Trinity::FriendlyCCedInRange u_check(m_creature, range); - Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange> searcher(pList, u_check); + Trinity::CreatureListSearcher<Trinity::FriendlyCCedInRange> searcher(m_creature, pList, u_check); m_creature->VisitNearbyObject(range, searcher); return pList; } @@ -790,7 +788,7 @@ std::list<Creature*> ScriptedAI::DoFindFriendlyMissingBuff(float range, uint32 s { std::list<Creature*> pList; Trinity::FriendlyMissingBuffInRange u_check(m_creature, range, spellid); - Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange> searcher(pList, u_check); + Trinity::CreatureListSearcher<Trinity::FriendlyMissingBuffInRange> searcher(m_creature, pList, u_check); m_creature->VisitNearbyObject(range, searcher); return pList; } diff --git a/src/bindings/scripts/include/sc_creature.h b/src/bindings/scripts/include/sc_creature.h index aadfdd3d19f..866007cc52a 100644 --- a/src/bindings/scripts/include/sc_creature.h +++ b/src/bindings/scripts/include/sc_creature.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +/* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * Thanks to the original authors: ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * diff --git a/src/bindings/scripts/include/sc_gossip.h b/src/bindings/scripts/include/sc_gossip.h index ec4ba0ae3f9..ead61740cdf 100644 --- a/src/bindings/scripts/include/sc_gossip.h +++ b/src/bindings/scripts/include/sc_gossip.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +/* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * Thanks to the original authors: ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * diff --git a/src/bindings/scripts/scripts/npc/npcs_special.cpp b/src/bindings/scripts/scripts/npc/npcs_special.cpp index d0131bf4067..ba315b6f866 100644 --- a/src/bindings/scripts/scripts/npc/npcs_special.cpp +++ b/src/bindings/scripts/scripts/npc/npcs_special.cpp @@ -351,7 +351,7 @@ struct TRINITY_DLL_DECL npc_injured_patientAI : public ScriptedAI //no regen health m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); //to make them lay with face down - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_DEAD); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); uint32 mobId = m_creature->GetEntry(); @@ -392,7 +392,7 @@ struct TRINITY_DLL_DECL npc_injured_patientAI : public ScriptedAI //regen health m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); //stand up - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); DoSay(SAY_DOC1,LANG_UNIVERSAL,NULL); uint32 mobId = m_creature->GetEntry(); diff --git a/src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp b/src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp index d1acc9373c4..90bbaac9705 100644 --- a/src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp +++ b/src/bindings/scripts/scripts/zone/azuremyst_isle/azuremyst_isle.cpp @@ -562,7 +562,7 @@ struct TRINITY_DLL_DECL npc_geezleAI : public ScriptedAI cell.SetNoCreate(); Trinity::AllGameObjectsWithEntryInGrid go_check(GO_NAGA_FLAG); - Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInGrid> go_search(FlagList, go_check); + Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInGrid> go_search(m_creature, FlagList, go_check); TypeContainerVisitor <Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInGrid>, GridTypeMapContainer> go_visit(go_search); CellLock<GridReadGuard> cell_lock(cell, pair); diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp index 813705739a5..4c796293aa3 100644 --- a/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_illidan.cpp @@ -137,6 +137,9 @@ EndScriptData */ #define FLAME_ENRAGE_DISTANCE 30 #define FLAME_CHARGE_DISTANCE 50 +#define ITEM_ID_MAIN_HAND 32837 +#define ITEM_ID_OFF_HAND 32838 + /**** Creature Summon and Recognition IDs ****/ enum CreatureEntry { @@ -454,7 +457,7 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI { GameObject* Door = GameObject::GetGameObject((*m_creature), pInstance->GetData64(i)); if(Door) - Door->SetUInt32Value(GAMEOBJECT_STATE, 0); // Open Doors + Door->SetGoState(0); // Open Doors } } @@ -487,10 +490,10 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI { if(spell->Id == SPELL_GLAIVE_RETURNS) // Re-equip our warblades! { - if(!m_creature->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY)) - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479); + if(!m_creature->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID)) + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 45479); else - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 45481); m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); } } @@ -567,8 +570,8 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI Timer[EVENT_FLIGHT_SEQUENCE] = 700; break; case 4://throw another - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); { uint8 i=0; Creature* Glaive = m_creature->SummonCreature(BLADE_OF_AZZINOTH, GlaivePosition[i].x, GlaivePosition[i].y, GlaivePosition[i].z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); @@ -653,14 +656,14 @@ struct TRINITY_DLL_DECL boss_illidan_stormrageAI : public ScriptedAI if(DemonTransformation[TransformCount].equip) { - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479); // Requip warglaives if needed - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 45479); // Requip warglaives if needed + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 45481); m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); } else { - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); // Unequip warglaives if needed - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+0, 0); // Unequip warglaives if needed + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); } switch(TransformCount) @@ -999,10 +1002,10 @@ struct TRINITY_DLL_DECL npc_akama_illidanAI : public ScriptedAI DoorGUID[1] = pInstance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_L); if(GETGO(Gate, GateGUID)) - Gate->SetUInt32Value(GAMEOBJECT_STATE, 1); + Gate->SetGoState(1); for(uint8 i = 0; i < 2; i++) if(GETGO(Door, DoorGUID[i])) - Door->SetUInt32Value(GAMEOBJECT_STATE, 1); + Door->SetGoState(1); } else { @@ -1072,7 +1075,7 @@ struct TRINITY_DLL_DECL npc_akama_illidanAI : public ScriptedAI for(uint8 i = 0; i < 2; i++) if(GETGO(Door, DoorGUID[i])) - Door->SetUInt32Value(GAMEOBJECT_STATE, 1); + Door->SetGoState(1); if(GETCRE(Illidan, IllidanGUID)) { @@ -1238,7 +1241,7 @@ struct TRINITY_DLL_DECL npc_akama_illidanAI : public ScriptedAI Spirit[0]->InterruptNonMeleeSpells(true); Spirit[1]->InterruptNonMeleeSpells(true); if(GETGO(Gate, GateGUID)) - Gate->SetUInt32Value(GAMEOBJECT_STATE, 0); + Gate->SetGoState(0); Timer = 2000; break; case 4: @@ -1269,7 +1272,7 @@ struct TRINITY_DLL_DECL npc_akama_illidanAI : public ScriptedAI case 6: for(uint8 i = 0; i < 2; i++) if(GETGO(Door, DoorGUID[i])) - Door->SetUInt32Value(GAMEOBJECT_STATE, 0); + Door->SetGoState(0); break; case 8: if(Phase == PHASE_WALK) @@ -1379,9 +1382,9 @@ struct TRINITY_DLL_DECL boss_maievAI : public ScriptedAI Timer[EVENT_MAIEV_STEALTH] = 0; Timer[EVENT_MAIEV_TAUNT] = 22000 + rand()%21 * 1000; Timer[EVENT_MAIEV_SHADOW_STRIKE] = 30000; - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 44850); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 1, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 2, 45738); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 44850); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, 45738); } void Aggro(Unit *who) {} @@ -1659,7 +1662,7 @@ bool GOHello_cage_trap(Player* plr, GameObject* go) // Grid search for nearest live creature of entry 23304 within 10 yards Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck check(*plr, 23304, true, 10); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(trigger, check); + Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(plr, trigger, check); TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer> cSearcher(searcher); @@ -1667,7 +1670,7 @@ bool GOHello_cage_trap(Player* plr, GameObject* go) cell_lock->Visit(cell_lock, cSearcher, *(plr->GetMap())); ((cage_trap_triggerAI*)trigger->AI())->Active = true; - go->SetUInt32Value(GAMEOBJECT_STATE, 0); + go->SetGoState(0); return true; } @@ -1831,8 +1834,8 @@ void boss_illidan_stormrageAI::Reset() m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_2); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING + MOVEMENTFLAG_ONTRANSPORT); m_creature->setActive(false); Summons.DespawnAll(); @@ -1889,8 +1892,8 @@ void boss_illidan_stormrageAI::HandleTalkSequence() m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); break; case 8: - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479); // Equip our warglaives! - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 45479); // Equip our warglaives! + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 45481); m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); break; @@ -1950,7 +1953,7 @@ void boss_illidan_stormrageAI::HandleTalkSequence() { Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); Maiev->setDeathState(JUST_DIED); - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,PLAYER_STATE_DEAD); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); } break; case 21: // Kill ourself. diff --git a/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp b/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp index d2b2da6d866..7315c7b3490 100644 --- a/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp +++ b/src/bindings/scripts/scripts/zone/black_temple/boss_shade_of_akama.cpp @@ -346,7 +346,7 @@ struct TRINITY_DLL_DECL boss_shade_of_akamaAI : public ScriptedAI std::list<Creature*> ChannelerList; Trinity::AllCreaturesOfEntryInRange check(m_creature, CREATURE_CHANNELER, 50); - Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(ChannelerList, check); + Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(m_creature, ChannelerList, check); TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> visitor(searcher); CellLock<GridReadGuard> cell_lock(cell, pair); diff --git a/src/bindings/scripts/scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp b/src/bindings/scripts/scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp index 8b08011bc8a..f56bd53e8fa 100644 --- a/src/bindings/scripts/scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp +++ b/src/bindings/scripts/scripts/zone/blades_edge_mountains/blades_edge_mountains.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Blades_Edge_Mountains SD%Complete: 90 -SDComment: Quest support: 10503, 10504, 10556, 10609, 10682, 10980. Ogri'la->Skettis Flight. (npc_daranelle needs bit more work before consider complete) +SDComment: Quest support: 10503, 10504, 10556, 10609, 10682, 10821, 10980. Ogri'la->Skettis Flight. (npc_daranelle needs bit more work before consider complete) SDCategory: Blade's Edge Mountains EndScriptData */ @@ -28,10 +28,20 @@ npc_daranelle npc_overseer_nuaar npc_saikkal_the_elder npc_skyguard_handler_irena +go_legion_obelisk EndContentData */ #include "precompiled.h" +//Support for quest: You're Fired! (10821) +bool obelisk_one, obelisk_two, obelisk_three, obelisk_four, obelisk_five; + +#define LEGION_OBELISK_ONE 185193 +#define LEGION_OBELISK_TWO 185195 +#define LEGION_OBELISK_THREE 185196 +#define LEGION_OBELISK_FOUR 185197 +#define LEGION_OBELISK_FIVE 185198 + /*###### ## mobs_bladespire_ogre ######*/ @@ -392,6 +402,48 @@ bool GossipSelect_npc_skyguard_handler_irena(Player *player, Creature *_Creature } /*###### +## go_legion_obelisk +######*/ + +bool GOHello_go_legion_obelisk(Player *player, GameObject* _GO) +{ + if ( player->GetQuestStatus(10821) == QUEST_STATUS_INCOMPLETE ) + { + switch( _GO->GetEntry() ) + { + case LEGION_OBELISK_ONE: + obelisk_one = true; + break; + case LEGION_OBELISK_TWO: + obelisk_two = true; + break; + case LEGION_OBELISK_THREE: + obelisk_three = true; + break; + case LEGION_OBELISK_FOUR: + obelisk_four = true; + break; + case LEGION_OBELISK_FIVE: + obelisk_five = true; + break; + } + + if ( obelisk_one == true && obelisk_two == true && obelisk_three == true && obelisk_four == true && obelisk_five == true ) + { + _GO->SummonCreature(19963,2943.40f,4778.20f,284.49f,0.94f,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,120000); + //reset global var + obelisk_one = false; + obelisk_two = false; + obelisk_three = false; + obelisk_four = false; + obelisk_five = false; + } + } + + return true; +} + +/*###### ## AddSC ######*/ @@ -425,6 +477,11 @@ void AddSC_blades_edge_mountains() newscript->pGossipHello = &GossipHello_npc_saikkal_the_elder; newscript->pGossipSelect = &GossipSelect_npc_saikkal_the_elder; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="go_legion_obelisk"; + newscript->pGOHello = &GOHello_go_legion_obelisk; + newscript->RegisterSelf(); newscript = new Script; newscript->Name="npc_skyguard_handler_irena"; diff --git a/src/bindings/scripts/scripts/zone/bloodmyst_isle/bloodmyst_isle.cpp b/src/bindings/scripts/scripts/zone/bloodmyst_isle/bloodmyst_isle.cpp index f298f3fa22a..3c3a622b49d 100644 --- a/src/bindings/scripts/scripts/zone/bloodmyst_isle/bloodmyst_isle.cpp +++ b/src/bindings/scripts/scripts/zone/bloodmyst_isle/bloodmyst_isle.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2008 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> +/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or diff --git a/src/bindings/scripts/scripts/zone/borean_tundra/borean_tundra.cpp b/src/bindings/scripts/scripts/zone/borean_tundra/borean_tundra.cpp new file mode 100644 index 00000000000..c776c1f9271 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/borean_tundra/borean_tundra.cpp @@ -0,0 +1,105 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Borean_Tundra +SD%Complete: 100 +SDComment: +SDCategory: Borean Tundra +EndScriptData */ + +/* ContentData +npc_tiare +npc_surristrasz +EndContentData */ + +#include "precompiled.h" + +/*###### +## npc_tiare +######*/ + +#define GOSSIP_ITEM_TELEPORT "Teleport me to Amber Ledge, please." + +bool GossipHello_npc_tiare(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_GOSSIP); + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_tiare(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_OPTION_GOSSIP) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,50135,true); + } + return true; +} + +/*###### +## npc_surristrasz +######*/ + +#define GOSSIP_ITEM_FREE_FLIGHT "I'd like passage to the Transitus Shield." +#define GOSSIP_ITEM_FLIGHT "May I use a drake to fly elsewhere?" + +bool GossipHello_npc_surristrasz(Player *player, Creature *_Creature) +{ + if (_Creature->isQuestGiver()) + player->PrepareQuestMenu(_Creature->GetGUID()); + + if (_Creature->isTaxi()) + { + player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM_FREE_FLIGHT, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_GOSSIP); + player->ADD_GOSSIP_ITEM(2, GOSSIP_ITEM_FLIGHT, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_TAXIVENDOR); + } + + player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_surristrasz(Player *player, Creature *_Creature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_OPTION_GOSSIP) + { + player->CLOSE_GOSSIP_MENU(); + player->CastSpell(player,46064,true); //TaxiPath 795 (amber to coldarra) + } + if (action == GOSSIP_OPTION_TAXIVENDOR) + { + player->GetSession()->SendTaxiMenu(_Creature); + } + return true; +} + +void AddSC_borean_tundra() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_tiare"; + newscript->pGossipHello = &GossipHello_npc_tiare; + newscript->pGossipSelect = &GossipSelect_npc_tiare; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_surristrasz"; + newscript->pGossipHello = &GossipHello_npc_surristrasz; + newscript->pGossipSelect = &GossipSelect_npc_surristrasz; + newscript->RegisterSelf(); +} diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp index 8b3eb0525dc..6e1e028cc70 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/hyjal/hyjalAI.cpp @@ -324,7 +324,7 @@ void hyjalAI::Retreat() // First get all creatures. std::list<Creature*> creatures; Trinity::AllFriendlyCreaturesInGrid creature_check(m_creature); - Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid> creature_searcher(creatures, creature_check); + Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid> creature_searcher(m_creature, creatures, creature_check); TypeContainerVisitor <Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid>, GridTypeMapContainer> creature_visitor(creature_searcher); @@ -332,7 +332,7 @@ void hyjalAI::Retreat() // Then get all Ancient Gem Veins. NOTE: Grid Search will only be able to find those in the grid. std::list<GameObject*> goList; Trinity::AllGameObjectsWithEntryInGrid go_check(185557); - Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInGrid> go_search(goList, go_check); + Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInGrid> go_search(m_creature, goList, go_check); TypeContainerVisitor <Trinity::GameObjectListSearcher<Trinity::AllGameObjectsWithEntryInGrid>, GridTypeMapContainer> go_visit(go_search); diff --git a/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp index e3aeaf55605..11462385674 100644 --- a/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp +++ b/src/bindings/scripts/scripts/zone/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp @@ -235,12 +235,12 @@ struct TRINITY_DLL_DECL npc_thrall_old_hillsbradAI : public npc_escortAI case 9: DoScriptText(SAY_TH_ARMORY, m_creature); m_creature->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, THRALL_WEAPON_MODEL); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, THRALL_WEAPON_INFO); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 781); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, THRALL_SHIELD_MODEL); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, THRALL_SHIELD_INFO); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 1038); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, THRALL_WEAPON_MODEL); + //m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, THRALL_WEAPON_INFO); + //m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 781); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, THRALL_SHIELD_MODEL); + //m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, THRALL_SHIELD_INFO); + //m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 1038); break; case 10: m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, THRALL_MODEL_EQUIPPED); @@ -399,12 +399,8 @@ struct TRINITY_DLL_DECL npc_thrall_old_hillsbradAI : public npc_escortAI { DoUnmount(); HadMount = false; - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, THRALL_MODEL_UNEQUIPPED); } if( IsBeingEscorted ) diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp index 1643f1068cf..4827de39a7a 100644 --- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp @@ -198,8 +198,8 @@ struct TRINITY_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI m_creature->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true); m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT,SPELL_EFFECT_ATTACK_ME, true); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY , 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); m_creature->CastSpell(m_creature, SPELL_DUAL_WIELD, true); m_creature->SetCorpseDelay(1000*60*60); if(pInstance) @@ -277,7 +277,7 @@ struct TRINITY_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI m_creature->RemoveAurasDueToSpell(AURA_BANISH); // Leotheras is getting immune again - m_creature->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, true); + m_creature->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, 1<<MECHANIC_BANISH, true); // changing model to bloodelf m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_NIGHTELF); @@ -298,15 +298,15 @@ struct TRINITY_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI { // channelers != 0 apply banish aura // removing Leotheras banish immune to apply AURA_BANISH - m_creature->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, false); + m_creature->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, 1<<MECHANIC_BANISH, false); DoCast(m_creature, AURA_BANISH); // changing model m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_DEMON); // and removing weapons - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY , 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); } } @@ -469,8 +469,8 @@ struct TRINITY_DLL_DECL boss_leotheras_the_blindAI : public ScriptedAI m_creature->RemoveAurasDueToSpell(SPELL_WHIRLWIND,0); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, MODEL_DEMON); DoScriptText(SAY_SWITCH_TO_DEMON, m_creature); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY , 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); DemonForm = true; NeedThreatReset = true; SwitchToDemon_Timer = 45000; diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp index 919a455bb79..5b4085335c3 100644 --- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp @@ -137,7 +137,7 @@ struct TRINITY_DLL_DECL instance_serpentshrine_cavern : public ScriptedInstance void OpenDoor(uint64 DoorGUID, bool open) { if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID)) - Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1); + Door->SetGoState(open ? 0 : 1); } void OnCreatureCreate(Creature *creature, uint32 creature_entry) diff --git a/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp index efa5cf72eaa..23985bdbdff 100644 --- a/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp +++ b/src/bindings/scripts/scripts/zone/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp @@ -145,7 +145,7 @@ struct TRINITY_DLL_DECL boss_warlord_kalithreshAI : public ScriptedAI cell.SetNoCreate(); Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck creature_check(*m_creature, entry, true, range); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(pCreature, creature_check); + Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_creature, pCreature, creature_check); TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer> creature_searcher(searcher); diff --git a/src/bindings/scripts/scripts/zone/deadmines/deadmines.cpp b/src/bindings/scripts/scripts/zone/deadmines/deadmines.cpp index 4bd33af98df..dfa3540857e 100644 --- a/src/bindings/scripts/scripts/zone/deadmines/deadmines.cpp +++ b/src/bindings/scripts/scripts/zone/deadmines/deadmines.cpp @@ -120,13 +120,13 @@ struct TRINITY_DLL_DECL instance_deadmines : public ScriptedInstance void ShootCannon() { - DefiasCannon->SetUInt32Value(GAMEOBJECT_STATE, 0); + DefiasCannon->SetGoState(0); DoPlaySound(DefiasCannon, SOUND_CANNONFIRE); } void BlastOutDoor() { - IronCladDoor->SetUInt32Value(GAMEOBJECT_STATE, 2); + IronCladDoor->SetGoState(2); DoPlaySound(IronCladDoor, SOUND_DESTROYDOOR); } diff --git a/src/bindings/scripts/scripts/zone/eastern_plaguelands/eastern_plaguelands.cpp b/src/bindings/scripts/scripts/zone/eastern_plaguelands/eastern_plaguelands.cpp index 44abf0da806..f0b073f5aa0 100644 --- a/src/bindings/scripts/scripts/zone/eastern_plaguelands/eastern_plaguelands.cpp +++ b/src/bindings/scripts/scripts/zone/eastern_plaguelands/eastern_plaguelands.cpp @@ -118,7 +118,7 @@ bool GossipHello_npc_tirion_fordring(Player *player, Creature *_Creature) if (_Creature->isQuestGiver()) player->PrepareQuestMenu( _Creature->GetGUID() ); - if (player->GetQuestStatus(5742) == QUEST_STATUS_INCOMPLETE && player->getStandState() == PLAYER_STATE_SIT ) + if (player->GetQuestStatus(5742) == QUEST_STATUS_INCOMPLETE && player->getStandState() == UNIT_STAND_STATE_SIT ) player->ADD_GOSSIP_ITEM( 0, "I am ready to hear your tale, Tirion.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); diff --git a/src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp b/src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp index 1aa7a6259d9..a0f0c57fdf9 100644 --- a/src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp +++ b/src/bindings/scripts/scripts/zone/eversong_woods/eversong_woods.cpp @@ -229,7 +229,7 @@ struct TRINITY_DLL_DECL npc_secondTrialAI : public ScriptedAI questPhase = 0; summonerGuid = 0; - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_KNEEL); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_KNEEL); m_creature->setFaction(FACTION_FRIENDLY); spellFlashLight = false; @@ -268,7 +268,7 @@ struct TRINITY_DLL_DECL npc_secondTrialAI : public ScriptedAI if ( questPhase == 1 ) { if ( timer < diff ) { - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); m_creature->setFaction(FACTION_HOSTILE); questPhase = 0; @@ -539,7 +539,7 @@ bool GOHello_go_second_trial(Player *player, GameObject* _GO) Creature* event_controller = NULL; Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*_GO, MASTER_KELERUN_BLOODMOURN, true, 30); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(event_controller, u_check); + Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(player, event_controller, u_check); TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); //cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(_GO->GetMap(), _GO)); cell_lock->Visit(cell_lock, grid_unit_searcher, *(_GO->GetMap())); diff --git a/src/bindings/scripts/scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp b/src/bindings/scripts/scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp index e0d3aea7d06..63f9becac3f 100644 --- a/src/bindings/scripts/scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp +++ b/src/bindings/scripts/scripts/zone/gruuls_lair/boss_high_king_maulgar.cpp @@ -238,8 +238,8 @@ struct TRINITY_DLL_DECL boss_high_king_maulgarAI : public ScriptedAI DoScriptText(SAY_ENRAGE, m_creature); m_creature->CastSpell(m_creature, SPELL_DUAL_WIELD, true); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); } if(Phase2) diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_nightbane.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_nightbane.cpp index 1a3c6684bbd..cc0645ce47d 100644 --- a/src/bindings/scripts/scripts/zone/karazhan/boss_nightbane.cpp +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_nightbane.cpp @@ -136,9 +136,9 @@ struct TRINITY_DLL_DECL boss_nightbaneAI : public ScriptedAI void HandleTerraceDoors(bool open) { if(GameObject *Door = GameObject::GetGameObject((*m_creature),pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_1))) - Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1); + Door->SetGoState(open ? 0 : 1); if(GameObject *Door = GameObject::GetGameObject((*m_creature),pInstance->GetData64(DATA_MASTERS_TERRACE_DOOR_2))) - Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1); + Door->SetGoState(open ? 0 : 1); } void Aggro(Unit *who) diff --git a/src/bindings/scripts/scripts/zone/karazhan/boss_prince_malchezaar.cpp b/src/bindings/scripts/scripts/zone/karazhan/boss_prince_malchezaar.cpp index 34a1114a12d..84dc686b73d 100644 --- a/src/bindings/scripts/scripts/zone/karazhan/boss_prince_malchezaar.cpp +++ b/src/bindings/scripts/scripts/zone/karazhan/boss_prince_malchezaar.cpp @@ -289,11 +289,11 @@ struct TRINITY_DLL_DECL boss_malchezaarAI : public ScriptedAI void ClearWeapons() { - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + //m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + //m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, 0); //damage const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); @@ -433,11 +433,11 @@ struct TRINITY_DLL_DECL boss_malchezaarAI : public ScriptedAI m_creature->CastSpell(m_creature, SPELL_THRASH_AURA, true); //models - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, AXE_EQUIP_MODEL); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, AXE_EQUIP_INFO); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, AXE_EQUIP_MODEL); + //m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, AXE_EQUIP_INFO); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, AXE_EQUIP_MODEL); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, AXE_EQUIP_INFO); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, AXE_EQUIP_MODEL); + //m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, AXE_EQUIP_INFO); //damage const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); @@ -475,8 +475,8 @@ struct TRINITY_DLL_DECL boss_malchezaarAI : public ScriptedAI Creature *axe = m_creature->SummonCreature(MALCHEZARS_AXE, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); if(axe) { - axe->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, AXE_EQUIP_MODEL); - axe->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, AXE_EQUIP_INFO); + axe->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, AXE_EQUIP_MODEL); + //axe->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, AXE_EQUIP_INFO); axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); axe->setFaction(m_creature->getFaction()); diff --git a/src/bindings/scripts/scripts/zone/karazhan/bosses_opera.cpp b/src/bindings/scripts/scripts/zone/karazhan/bosses_opera.cpp index 10828248927..b5dfc875984 100644 --- a/src/bindings/scripts/scripts/zone/karazhan/bosses_opera.cpp +++ b/src/bindings/scripts/scripts/zone/karazhan/bosses_opera.cpp @@ -905,7 +905,7 @@ void PretendToDie(Creature* _Creature) _Creature->SetUInt64Value(UNIT_FIELD_TARGET,0); _Creature->GetMotionMaster()->Clear(); _Creature->GetMotionMaster()->MoveIdle(); - _Creature->SetUInt32Value(UNIT_FIELD_BYTES_1,PLAYER_STATE_DEAD); + _Creature->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); }; void Resurrect(Creature* target) diff --git a/src/bindings/scripts/scripts/zone/nagrand/nagrand.cpp b/src/bindings/scripts/scripts/zone/nagrand/nagrand.cpp index 3ee4f06d629..92b179eefec 100644 --- a/src/bindings/scripts/scripts/zone/nagrand/nagrand.cpp +++ b/src/bindings/scripts/scripts/zone/nagrand/nagrand.cpp @@ -125,7 +125,7 @@ struct TRINITY_DLL_DECL mob_lumpAI : public ScriptedAI m_creature->DeleteThreatList(); m_creature->CombatStop(); m_creature->setFaction(1080); //friendly - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_SIT); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_SIT); DoScriptText(LUMP_DEFEAT, m_creature); bReset = true; @@ -139,7 +139,7 @@ struct TRINITY_DLL_DECL mob_lumpAI : public ScriptedAI m_creature->RemoveAura(SPELL_VISUAL_SLEEP,0); if (!m_creature->IsStandState()) - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); switch(rand()%2) { diff --git a/src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp b/src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp index fc27da1b649..20eb88a538b 100644 --- a/src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp +++ b/src/bindings/scripts/scripts/zone/netherstorm/netherstorm.cpp @@ -404,7 +404,7 @@ struct TRINITY_DLL_DECL npc_commander_dawnforgeAI : public ScriptedAI cell.SetNoCreate(); Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck creature_check(*m_creature, entry, true, range); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(pCreature, creature_check); + Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_creature, pCreature, creature_check); TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer> creature_searcher(searcher); @@ -441,8 +441,8 @@ struct TRINITY_DLL_DECL npc_commander_dawnforgeAI : public ScriptedAI ardonis->SendUpdateToPlayer(player); //Set them to kneel - m_creature->SetStandState(PLAYER_STATE_KNEEL); - ardonis->SetStandState(PLAYER_STATE_KNEEL); + m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); + ardonis->SetStandState(UNIT_STAND_STATE_KNEEL); } //Set them back to each other @@ -466,8 +466,8 @@ struct TRINITY_DLL_DECL npc_commander_dawnforgeAI : public ScriptedAI ardonis->SendUpdateToPlayer(player); //Set state - m_creature->SetStandState(PLAYER_STATE_NONE); - ardonis->SetStandState(PLAYER_STATE_NONE); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + ardonis->SetStandState(UNIT_STAND_STATE_STAND); } } @@ -639,7 +639,7 @@ Creature* SearchDawnforge(Player *source, uint32 entry, float range) cell.SetNoCreate(); Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck creature_check(*source, entry, true, range); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(pCreature, creature_check); + Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(source, pCreature, creature_check); TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer> creature_searcher(searcher); diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_headless_horseman.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_headless_horseman.cpp index 66270e79539..ac8d941fa07 100644 --- a/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_headless_horseman.cpp +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/boss_headless_horseman.cpp @@ -573,7 +573,7 @@ struct TRINITY_DLL_DECL boss_headless_horsemanAI : public ScriptedAI DoCast(m_creature,SPELL_BODY_REGEN,true); m_creature->CastSpell(Head, SPELL_FLYING_HEAD,true); DoCast(m_creature,SPELL_CONFUSE,false); //test - done_by->ProcDamageAndSpell(m_creature,PROC_FLAG_KILL_AND_GET_XP,PROC_FLAG_KILLED,PROC_EX_NONE,0); + done_by->ProcDamageAndSpell(m_creature,PROC_FLAG_KILL,PROC_FLAG_KILLED,PROC_EX_NONE,0); whirlwind = 4000 + (rand()%5)*1000; regen = 0; } @@ -736,7 +736,7 @@ struct TRINITY_DLL_DECL mob_pulsing_pumpkinAI : public ScriptedAI sprouted = false; DoCast(m_creature,SPELL_PUMPKIN_AURA,true); DoCast(m_creature,SPELL_SPROUTING); - m_creature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_ROTATE); + m_creature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED); } void Aggro(Unit *who){} @@ -747,7 +747,7 @@ struct TRINITY_DLL_DECL mob_pulsing_pumpkinAI : public ScriptedAI { sprouted = true; m_creature->RemoveAllAuras(); - m_creature->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISABLE_ROTATE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_STUNNED); DoCast(m_creature,SPELL_SPROUT_BODY,true); m_creature->UpdateEntry(PUMPKIN_FIEND); DoStartMovement(m_creature->getVictim()); diff --git a/src/bindings/scripts/scripts/zone/scarlet_monastery/instance_scarlet_monastery.cpp b/src/bindings/scripts/scripts/zone/scarlet_monastery/instance_scarlet_monastery.cpp index 953ae804e39..1a94123f383 100644 --- a/src/bindings/scripts/scripts/zone/scarlet_monastery/instance_scarlet_monastery.cpp +++ b/src/bindings/scripts/scripts/zone/scarlet_monastery/instance_scarlet_monastery.cpp @@ -92,7 +92,7 @@ struct TRINITY_DLL_DECL instance_scarlet_monastery : public ScriptedInstance { GameObject *Shrine = instance->GetGameObjectInMap(PumpkinShrineGUID); if(Shrine) - Shrine->SetUInt32Value(GAMEOBJECT_STATE,1); + Shrine->SetGoState(1); }break; case DATA_HORSEMAN_EVENT: if (data == DONE) @@ -106,7 +106,7 @@ struct TRINITY_DLL_DECL instance_scarlet_monastery : public ScriptedInstance HorsemanAdds.clear(); GameObject *Shrine = instance->GetGameObjectInMap(PumpkinShrineGUID); if(Shrine) - Shrine->SetUInt32Value(GAMEOBJECT_STATE,1); + Shrine->SetGoState(1); } break; } diff --git a/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp b/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp index 6a11c455f67..b09cdce5c20 100644 --- a/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp +++ b/src/bindings/scripts/scripts/zone/stormwind/stormwind_city.cpp @@ -27,6 +27,7 @@ npc_bartleby npc_dashel_stonefist npc_general_marcus_jonathan npc_lady_katrana_prestor +npc_harbor_taxi EndContentData */ #include "precompiled.h" @@ -236,6 +237,28 @@ bool GossipSelect_npc_lady_katrana_prestor(Player *player, Creature *_Creature, return true; } +/*###### +## npc_harbor_taxi +######*/ + +#define GOSSIP_STORMWIND "I'd like to take a flight around Stormwind Harbor." + +bool GossipHello_npc_stormwind_harbor_taxi(Player *player, Creature *_Creature) +{ + player->ADD_GOSSIP_ITEM(0, GOSSIP_STORMWIND, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10); + player->SEND_GOSSIP_MENU(13454,_Creature->GetGUID()); + return true; +} + +bool GossipSelect_npc_stormwind_harbor_taxi(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 10) + { + player->GetSession()->SendDoFlight(1149, 1041); + } + return true; +} + void AddSC_stormwind_city() { Script *newscript; @@ -268,4 +291,10 @@ void AddSC_stormwind_city() newscript->pGossipHello = &GossipHello_npc_lady_katrana_prestor; newscript->pGossipSelect = &GossipSelect_npc_lady_katrana_prestor; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="npc_stormwind_harbor_taxi"; + newscript->pGossipHello = &GossipHello_npc_stormwind_harbor_taxi; + newscript->pGossipSelect = &GossipSelect_npc_stormwind_harbor_taxi; + newscript->RegisterSelf(); } diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp index 4dea21dd771..8afba94fa44 100644 --- a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_felmyst.cpp @@ -493,7 +493,7 @@ struct TRINITY_DLL_DECL boss_felmystAI : public ScriptedAI cell.SetNoCreate(); Trinity::AllCreaturesOfEntryInRange check(m_creature, entry, 100); - Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(templist, check); + Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(m_creature, templist, check); TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> cSearcher(searcher); diff --git a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp index 3c358c1f3b6..cab99d321f8 100644 --- a/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp +++ b/src/bindings/scripts/scripts/zone/sunwell_plateau/boss_kalecgos.cpp @@ -133,7 +133,7 @@ struct TRINITY_DLL_DECL boss_kalecgosAI : public ScriptedAI m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); m_creature->RemoveUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT + MOVEMENTFLAG_LEVITATING); m_creature->SetVisibility(VISIBILITY_ON); - m_creature->SetStandState(PLAYER_STATE_SLEEP); + m_creature->SetStandState(UNIT_STAND_STATE_SLEEP); ArcaneBuffetTimer = 8000; FrostBreathTimer = 15000; @@ -158,7 +158,7 @@ struct TRINITY_DLL_DECL boss_kalecgosAI : public ScriptedAI void Aggro(Unit* who) { - m_creature->SetStandState(PLAYER_STATE_NONE); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); DoScriptText(SAY_EVIL_AGGRO, m_creature); GameObject *Door = GameObject::GetGameObject(*m_creature, DoorGUID); if(Door) Door->SetLootState(GO_ACTIVATED); diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp index ec7036e4666..fed536832bf 100644 --- a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_alar.cpp @@ -228,12 +228,12 @@ struct TRINITY_DLL_DECL boss_alarAI : public ScriptedAI WaitEvent = WE_DUMMY; return; case WE_DIE: - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_DEAD); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); WaitTimer = 5000; WaitEvent = WE_REVIVE; return; case WE_REVIVE: - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); m_creature->SetHealth(m_creature->GetMaxHealth()); m_creature->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); diff --git a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp index 2c9df9cb219..342363eb9b2 100644 --- a/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp +++ b/src/bindings/scripts/scripts/zone/tempest_keep/the_eye/boss_kaelthas.cpp @@ -238,7 +238,7 @@ struct TRINITY_DLL_DECL advisorbase_ai : public ScriptedAI m_creature->SetUInt64Value(UNIT_FIELD_TARGET,0); m_creature->GetMotionMaster()->Clear(); m_creature->GetMotionMaster()->MoveIdle(); - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,PLAYER_STATE_DEAD); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); if (pInstance->GetData(DATA_KAELTHASEVENT) == 3) JustDied(pKiller); @@ -344,7 +344,7 @@ struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI std::list<Creature*> PhoenixList; Trinity::AllCreaturesOfEntryInRange check(m_creature, PHOENIX, 50); - Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(PhoenixList, check); + Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(m_creature, PhoenixList, check); TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> visitor(searcher); CellLock<GridReadGuard> cell_lock(cell, pair); @@ -575,7 +575,7 @@ struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI //Subphase 2 - Start case 2: Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[0])); - if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == PLAYER_STATE_DEAD)) + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD)) { DoScriptText(SAY_INTRO_SANGUINAR, m_creature); @@ -609,7 +609,7 @@ struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI //Subphase 3 - Start case 4: Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[1])); - if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == PLAYER_STATE_DEAD)) + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD)) { DoScriptText(SAY_INTRO_CAPERNIAN, m_creature); @@ -643,7 +643,7 @@ struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI //Subphase 4 - Start case 6: Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[2])); - if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == PLAYER_STATE_DEAD)) + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD)) { DoScriptText(SAY_INTRO_TELONICUS, m_creature); @@ -679,7 +679,7 @@ struct TRINITY_DLL_DECL boss_kaelthasAI : public ScriptedAI //End of phase 1 case 8: Advisor = (Creature*)(Unit::GetUnit((*m_creature), AdvisorGuid[3])); - if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == PLAYER_STATE_DEAD)) + if(Advisor && (Advisor->GetUInt32Value(UNIT_FIELD_BYTES_1) == UNIT_STAND_STATE_DEAD)) { Phase = 2; pInstance->SetData(DATA_KAELTHASEVENT, 2); @@ -1467,7 +1467,7 @@ struct TRINITY_DLL_DECL mob_phoenix_tkAI : public ScriptedAI if(SummonEgg == 1){ //hack die animation m_creature->RemoveAllAuras(); DoStartNoMovement(m_creature->getVictim()); - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_DEAD); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); SummonEgg = 2; Cycle_Timer = 1000; } diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp index 97a4e26536c..4223261f23e 100644 --- a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/boss_twinemperors.cpp @@ -336,7 +336,7 @@ struct TRINITY_DLL_DECL boss_twinemperorsAI : public ScriptedAI std::list<Creature*> unitList; AnyBugCheck u_check(m_creature, 150); - Trinity::CreatureListSearcher<AnyBugCheck> searcher(unitList, u_check); + Trinity::CreatureListSearcher<AnyBugCheck> searcher(m_creature, unitList, u_check); TypeContainerVisitor<Trinity::CreatureListSearcher<AnyBugCheck>, GridTypeMapContainer > grid_creature_searcher(searcher); CellLock<GridReadGuard> cell_lock(cell, p); cell_lock->Visit(cell_lock, grid_creature_searcher, *(m_creature->GetMap())); diff --git a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp index 913bf6d9c68..56a94c27272 100644 --- a/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp +++ b/src/bindings/scripts/scripts/zone/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp @@ -175,7 +175,7 @@ struct TRINITY_DLL_DECL aqsentinelAI : public ScriptedAI std::list<Creature*> assistList; NearbyAQSentinel u_check(nears); - Trinity::CreatureListSearcher<NearbyAQSentinel> searcher(assistList, u_check); + Trinity::CreatureListSearcher<NearbyAQSentinel> searcher(m_creature, assistList, u_check); TypeContainerVisitor<Trinity::CreatureListSearcher<NearbyAQSentinel>, GridTypeMapContainer > grid_creature_searcher(searcher); CellLock<GridReadGuard> cell_lock(cell, p); cell_lock->Visit(cell_lock, grid_creature_searcher, *(nears->GetMap())); diff --git a/src/bindings/scripts/scripts/zone/terokkar_forest/terokkar_forest.cpp b/src/bindings/scripts/scripts/zone/terokkar_forest/terokkar_forest.cpp index 444e8b0a528..9bc5b231b7d 100644 --- a/src/bindings/scripts/scripts/zone/terokkar_forest/terokkar_forest.cpp +++ b/src/bindings/scripts/scripts/zone/terokkar_forest/terokkar_forest.cpp @@ -60,7 +60,7 @@ struct TRINITY_DLL_DECL mob_unkor_the_ruthlessAI : public ScriptedAI CanDoQuest = false; UnkorUnfriendly_Timer = 0; Pulverize_Timer = 3000; - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_NONE); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); m_creature->setFaction(FACTION_HOSTILE); } @@ -70,7 +70,7 @@ struct TRINITY_DLL_DECL mob_unkor_the_ruthlessAI : public ScriptedAI { DoScriptText(SAY_SUBMIT, m_creature); m_creature->setFaction(FACTION_FRIENDLY); - m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, PLAYER_STATE_SIT); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_SIT); m_creature->RemoveAllAuras(); m_creature->DeleteThreatList(); m_creature->CombatStop(); diff --git a/src/bindings/scripts/scripts/zone/tirisfal_glades/tirisfal_glades.cpp b/src/bindings/scripts/scripts/zone/tirisfal_glades/tirisfal_glades.cpp index 779466f2863..3f42f65b7e7 100644 --- a/src/bindings/scripts/scripts/zone/tirisfal_glades/tirisfal_glades.cpp +++ b/src/bindings/scripts/scripts/zone/tirisfal_glades/tirisfal_glades.cpp @@ -100,7 +100,7 @@ GameObject* SearchMausoleumGo(Unit *source, uint32 entry, float range) cell.SetNoCreate(); Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*source, entry, range); - Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> searcher(pGo, go_check); + Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> searcher(source, pGo, go_check); TypeContainerVisitor<Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer> go_searcher(searcher); diff --git a/src/bindings/scripts/scripts/zone/uldaman/instance_uldaman.cpp b/src/bindings/scripts/scripts/zone/uldaman/instance_uldaman.cpp index 08e1eeee423..bca17fcd031 100644 --- a/src/bindings/scripts/scripts/zone/uldaman/instance_uldaman.cpp +++ b/src/bindings/scripts/scripts/zone/uldaman/instance_uldaman.cpp @@ -70,7 +70,7 @@ struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance break; case ANCIENT_VAULT_DOOR: - go->SetUInt32Value(GAMEOBJECT_STATE,1); + go->SetGoState(1); go->SetUInt32Value(GAMEOBJECT_FLAGS, 33); ancientVaultDoor = go->GetGUID(); break; @@ -93,7 +93,7 @@ struct TRINITY_DLL_DECL instance_uldaman : public ScriptedInstance return; go->SetUInt32Value(GAMEOBJECT_FLAGS, 33); - go->SetUInt32Value(GAMEOBJECT_STATE, 0); + go->SetGoState(0); } void ActivateStoneKeepers() diff --git a/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/boss_keleseth.cpp b/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/boss_keleseth.cpp new file mode 100644 index 00000000000..c9d40cc1b77 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/boss_keleseth.cpp @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Prince_Keleseth +SD%Complete: 80 +SDComment: Normal and Heroic Support. Needs Prince Movements, Needs skeletons resurrection, Needs adjustments to blizzlike timers, Needs adjustments to use spell though. Needs Shadowbolt castbar +SDCategory: Utgarde Keep +EndScriptData */ + +#include "precompiled.h" +#include "def_keep.h" + +#define SPELL_SHADOWBOLT 43667 +#define SPELL_SHADOWBOLT_HEROIC 59389 +#define SPELL_FROST_TOMB 48400 +#define SPELL_FROST_TOMB_SUMMON 42714 +#define CREATURE_FROSTTOMB 23965 +#define CREATURE_SKELETON 23970 + +#define SAY_AGGRO -1574000 +#define SAY_KILL -1574001 +#define SAY_DEATH -1574002 +#define SAY_FROST_TOMB -1574003 +#define SAY_SKELETONS -1574004 + +#define SKELETONSPAWN_Z 42.8668 + +float SkeletonSpawnPoint[5][5]= +{ + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, +}; + +float AttackLoc[3]={197.636, 194.046, 40.8164}; + +struct TRINITY_DLL_DECL mob_frost_tombAI : public ScriptedAI +{ + mob_frost_tombAI(Creature *c) : ScriptedAI(c) + { + Reset(); + } + + uint64 FrostTombGUID; + + void Reset() + { + FrostTombGUID = 0; + } + + void Aggro(Unit* who) {} + void AttackStart(Unit* who) {} + void MoveInLineOfSight(Unit* who) {} + + void JustDied(Unit *killer) + { + if(FrostTombGUID) + { + Unit* FrostTomb = Unit::GetUnit((*m_creature),FrostTombGUID); + if(FrostTomb) + FrostTomb->RemoveAurasDueToSpell(SPELL_FROST_TOMB); + } + } +}; + +struct TRINITY_DLL_DECL boss_kelesethAI : public ScriptedAI +{ + boss_kelesethAI(Creature *c) : ScriptedAI(c) + { + pInstance = ((ScriptedInstance*)c->GetInstanceData()); + Reset(); + Heroic = c->GetMap()->IsHeroic(); + } + + ScriptedInstance* pInstance; + + uint32 FrostTombTimer; + uint32 SummonSkeletonsTimer; + uint32 RespawnSkeletonsTimer; + uint32 ShadowboltTimer; + uint64 SkeletonGUID[5]; + bool Skeletons; + bool Heroic; + bool RespawnSkeletons; + + void Reset() + { + ShadowboltTimer = 0; + Skeletons = false; + + ResetTimer(); + + if(pInstance) + pInstance->SetData(DATA_PRINCEKELESETH, NOT_STARTED); + } + + void KilledUnit(Unit *victim) + { + if(victim == m_creature) + return; + + DoScriptText(SAY_KILL, m_creature); + } + + void JustDied(Unit* killer) + { + if(pInstance) + pInstance->SetData(DATA_PRINCEKELESETH, DONE); + + DoScriptText(SAY_DEATH, m_creature); + } + + void Aggro(Unit* who) + { + if(pInstance) + pInstance->SetData(DATA_PRINCEKELESETH, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, m_creature); + DoZoneInCombat(); + } + + void ResetTimer(uint32 inc = 0) + { + SummonSkeletonsTimer = 5000 + inc; + FrostTombTimer = 28000 + inc; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if(ShadowboltTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + if(target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER) + m_creature->CastSpell(target, Heroic ? SPELL_SHADOWBOLT:SPELL_SHADOWBOLT_HEROIC, true); + ShadowboltTimer = 2000; + }else ShadowboltTimer -= diff; + + if((SummonSkeletonsTimer < diff) && !Skeletons) + { + Creature* Skeleton; + DoScriptText(SAY_SKELETONS, m_creature); + for(uint8 i = 0; i < 5; ++i) + { + Skeleton = m_creature->SummonCreature(CREATURE_SKELETON, SkeletonSpawnPoint[i][0], SkeletonSpawnPoint[i][1] , SKELETONSPAWN_Z, 0, TEMPSUMMON_MANUAL_DESPAWN,0); + if(Skeleton) + { + Skeleton->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Skeleton->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY() , m_creature->GetPositionZ()); + Skeleton->AddThreat(m_creature, 0.0f); + DoZoneInCombat(Skeleton); + } + } + Skeletons = true; + }else SummonSkeletonsTimer -= diff; + + if(FrostTombTimer < diff) + { + Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 1); + if(target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER) + { + DoCast(target, SAY_FROST_TOMB, true); + Creature* Chains = m_creature->SummonCreature(CREATURE_FROSTTOMB, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 20000); + if(Chains) + { + ((mob_frost_tombAI*)Chains->AI())->FrostTombGUID = target->GetGUID(); + Chains->CastSpell(target, SPELL_FROST_TOMB, true); + + DoScriptText(SAY_FROST_TOMB, m_creature); + + FrostTombTimer = 15000; + } + } + }else FrostTombTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_frost_tomb(Creature *_Creature) +{ + return new mob_frost_tombAI(_Creature); +} + +CreatureAI* GetAI_boss_keleseth(Creature *_Creature) +{ + return new boss_kelesethAI (_Creature); +} + +void AddSC_boss_keleseth() +{ + Script *newscript; + + newscript = new Script; + newscript->Name="boss_keleseth"; + newscript->GetAI = &GetAI_boss_keleseth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_tomb"; + newscript->GetAI = &GetAI_mob_frost_tomb; + newscript->RegisterSelf(); +} diff --git a/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/def_keep.h b/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/def_keep.h new file mode 100644 index 00000000000..4161c725fb2 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/def_keep.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_KEEP_H +#define DEF_KEEP_H + +#define DATA_PRINCEKELESETH 1 +#define DATA_DALRON 2 +#define DATA_SKARVALD 3 +#define DATA_INGVAR 4 +#endif diff --git a/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp b/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp new file mode 100644 index 00000000000..77672143f24 --- /dev/null +++ b/src/bindings/scripts/scripts/zone/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Utgarde_Keep +SD%Complete: 0 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Utgarde Keep Scripts +SDCategory: Utgarde Keep +EndScriptData */ + +#include "precompiled.h" +#include "def_keep.h" + +#define ENCOUNTERS 4 + +/* Utgarde Keep encounters: +0 - Prince Keleseth +1 - Skarvald +2 - Dalronn +3 - Ingvar the Plunderer +*/ + +struct TRINITY_DLL_DECL instance_utgarde_keep : public ScriptedInstance +{ + instance_utgarde_keep(Map *Map) : ScriptedInstance(Map) {Initialize();}; + + uint64 Keleseth; + uint64 Skarvald; + uint64 Dalronn; + uint64 Ingvar; + + bool IsBossDied[2]; + + uint32 Encounters[ENCOUNTERS]; + std::string str_data; + + void Initialize() + { + Keleseth = 0; + Skarvald = 0; + Dalronn =0; + Ingvar =0; + + for(uint8 i = 0; i < ENCOUNTERS; ++i) + Encounters[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 0; i < ENCOUNTERS; ++i) + if(Encounters[i] == IN_PROGRESS) return true; + + return false; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* plr = itr->getSource()) + return plr; + } + } + + debug_log("TSCR: Instance Utgarde Keep: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void HandleGameObject(uint64 guid, uint32 state) + { + Player *player = GetPlayerInMap(); + + if (!player || !guid) + { + debug_log("TSCR: Utgarde Keep: HandleGameObject fail"); + return; + } + + if (GameObject *go = GameObject::GetGameObject(*player,guid)) + go->SetGoState(state); + } + + void OnCreatureCreate(Creature *creature, uint32 creature_entry) + { + switch(creature->GetEntry()) + { + case 23953: Keleseth = creature->GetGUID(); break; + case 24200: Dalronn = creature->GetGUID(); break; + case 24201: Skarvald = creature->GetGUID(); break; + case 23954: Ingvar = creature->GetGUID(); break; + } + } + + void OnObjectCreate(GameObject* go) + { + switch(go->GetEntry()) + { + //door and object id + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_PRINCEKELESETH: return Keleseth; + case DATA_DALRON: return Dalronn; + case DATA_SKARVALD: return Skarvald; + case DATA_INGVAR: return Ingvar; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_PRINCEKELESETH: + if(data == DONE) + { + //HandleGameObject(doorname, 0); + } + Encounters[0] = data;break; + case DATA_DALRON: + if(data == DONE) + { + //HandleGameObject(doorname, 0); + } + Encounters[1] = data; break; + case DATA_SKARVALD: + if(data == DONE) + { + //HandleGameObject(doorname, 0); + } + Encounters[2] = data; break; + case DATA_INGVAR: + if(data == DONE) + { + //HandleGameObject(doorname, 0); + } + Encounters[3] = data; break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << Encounters[0] << " " << Encounters[1] << " " + << Encounters[2] << " " << Encounters[3]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_PRINCEKELESETH: return Encounters[0]; + case DATA_DALRON: return Encounters[1]; + case DATA_SKARVALD: return Encounters[2]; + case DATA_INGVAR: return Encounters[3]; + } + + return 0; + } + + const char* Save() + { + return str_data.c_str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> Encounters[0] >> Encounters[1] >> Encounters[2] + >> Encounters[3]; + + for(uint8 i = 0; i < ENCOUNTERS; ++i) + if (Encounters[i] == IN_PROGRESS) + Encounters[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_utgarde_keep(Map* map) +{ + return new instance_utgarde_keep(map); +} + +void AddSC_instance_utgarde_keep() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_utgarde_keep"; + newscript->GetInstanceData = &GetInstanceData_instance_utgarde_keep; + newscript->RegisterSelf(); +} diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp index 7eb9fb81426..4daff002f38 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_akilzon.cpp @@ -188,7 +188,7 @@ struct TRINITY_DLL_DECL boss_akilzonAI : public ScriptedAI { Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(m_creature, m_creature, 999); - Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(tempUnitMap, u_check); + Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(m_creature, tempUnitMap, u_check); TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp index fe31c5fbfc1..c2827ce6701 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_hexlord.cpp @@ -237,8 +237,7 @@ struct TRINITY_DLL_DECL boss_hex_lord_malacrassAI : public ScriptedAI SpawnAdds(); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 46916); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 50268674); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 46916); m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); } diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp index d7ce85055d3..b6792278127 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_janalai.cpp @@ -239,7 +239,7 @@ struct TRINITY_DLL_DECL boss_janalaiAI : public ScriptedAI cell.SetNoCreate(); Trinity::AllCreaturesOfEntryInRange check(m_creature, MOB_EGG, 100); - Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(templist, check); + Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(m_creature, templist, check); TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> cSearcher(searcher); @@ -274,7 +274,7 @@ struct TRINITY_DLL_DECL boss_janalaiAI : public ScriptedAI cell.SetNoCreate(); Trinity::AllCreaturesOfEntryInRange check(m_creature, MOB_FIRE_BOMB, 100); - Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(templist, check); + Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(m_creature, templist, check); TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> cSearcher(searcher); @@ -518,7 +518,7 @@ struct TRINITY_DLL_DECL mob_amanishi_hatcherAI : public ScriptedAI cell.SetNoCreate(); Trinity::AllCreaturesOfEntryInRange check(m_creature, 23817, 50); - Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(templist, check); + Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(m_creature, templist, check); TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllCreaturesOfEntryInRange>, GridTypeMapContainer> cSearcher(searcher); diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp index c1ef845d1f8..0220523a1e2 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_nalorakk.cpp @@ -143,7 +143,7 @@ struct TRINITY_DLL_DECL boss_nalorakkAI : public ScriptedAI Berserk_Timer = 600000; inBearForm = false; - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 1, 5122); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); } void SendAttacker(Unit* target) @@ -159,7 +159,7 @@ struct TRINITY_DLL_DECL boss_nalorakkAI : public ScriptedAI cell.SetNoCreate(); Trinity::AllFriendlyCreaturesInGrid check(m_creature); - Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid> searcher(templist, check); + Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid> searcher(m_creature, templist, check); TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid>, GridTypeMapContainer> cSearcher(searcher); @@ -361,7 +361,7 @@ struct TRINITY_DLL_DECL boss_nalorakkAI : public ScriptedAI { if(inBearForm) { - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 1, 5122); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); DoYell(YELL_SHIFTEDTOTROLL, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_YELL_TOTROLL); m_creature->RemoveAurasDueToSpell(SPELL_BEARFORM); @@ -373,7 +373,7 @@ struct TRINITY_DLL_DECL boss_nalorakkAI : public ScriptedAI } else { - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + 1, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 0); DoYell(YELL_SHIFTEDTOBEAR, LANG_UNIVERSAL, NULL); DoPlaySoundToSet(m_creature, SOUND_YELL_TOBEAR); DoCast(m_creature, SPELL_BEARFORM, true); diff --git a/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp b/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp index 685cfa57a0b..d4be29c3557 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/boss_zuljin.cpp @@ -207,9 +207,9 @@ struct TRINITY_DLL_DECL boss_zuljinAI : public ScriptedAI Summons.DespawnAll(); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 47174); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218172674); - m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 47174); + //m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, 218172674); + //m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); } void Aggro(Unit *who) @@ -253,7 +253,7 @@ struct TRINITY_DLL_DECL boss_zuljinAI : public ScriptedAI Summons.DespawnEntry(CREATURE_COLUMN_OF_FIRE); if(Unit *Temp = Unit::GetUnit(*m_creature, SpiritGUID[3])) - Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,PLAYER_STATE_DEAD); + Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); } void AttackStart(Unit *who) @@ -341,7 +341,7 @@ struct TRINITY_DLL_DECL boss_zuljinAI : public ScriptedAI m_creature->Relocate(CENTER_X, CENTER_Y, CENTER_Z,0); m_creature->SendMonsterMove(CENTER_X, CENTER_Y, CENTER_Z,0,0,100); DoResetThreat(); - m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); m_creature->RemoveAurasDueToSpell(Transform[Phase].unaura); DoCast(m_creature, Transform[Phase].spell); DoYell(Transform[Phase].text, LANG_UNIVERSAL, NULL); @@ -349,7 +349,7 @@ struct TRINITY_DLL_DECL boss_zuljinAI : public ScriptedAI if(Phase > 0) { if(Unit *Temp = Unit::GetUnit(*m_creature, SpiritGUID[Phase - 1])) - Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,PLAYER_STATE_DEAD); + Temp->SetUInt32Value(UNIT_FIELD_BYTES_1,UNIT_STAND_STATE_DEAD); } if(Unit *Temp = Unit::GetUnit(*m_creature, SpiritGUID[NextPhase - 1])) Temp->CastSpell(m_creature, SPELL_SIPHON_SOUL, false); // should m cast on temp diff --git a/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp b/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp index dff3148aa57..47e9c4395ba 100644 --- a/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp +++ b/src/bindings/scripts/scripts/zone/zulaman/instance_zulaman.cpp @@ -140,7 +140,7 @@ struct TRINITY_DLL_DECL instance_zulaman : public ScriptedInstance void OpenDoor(uint64 DoorGUID, bool open) { if(GameObject *Door = instance->GetGameObjectInMap(DoorGUID)) - Door->SetUInt32Value(GAMEOBJECT_STATE, open ? 0 : 1); + Door->SetGoState(open ? 0 : 1); } void SummonHostage(uint8 num) diff --git a/src/bindings/scripts/scripts/zone/zulgurub/boss_renataki.cpp b/src/bindings/scripts/scripts/zone/zulgurub/boss_renataki.cpp index 0dccc26ff14..10679d13812 100644 --- a/src/bindings/scripts/scripts/zone/zulgurub/boss_renataki.cpp +++ b/src/bindings/scripts/scripts/zone/zulgurub/boss_renataki.cpp @@ -65,9 +65,9 @@ struct TRINITY_DLL_DECL boss_renatakiAI : public ScriptedAI if (Invisible_Timer < diff) { m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); - m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0); - m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , 218171138); - m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, 3); + m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + //m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , 218171138); + //m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, 3); m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,11686); Invisible = true; @@ -100,9 +100,9 @@ struct TRINITY_DLL_DECL boss_renatakiAI : public ScriptedAI m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,15268); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 31818); - m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , 218171138); - m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, 3); + m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_ID, 31818); + //m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO , 218171138); + //m_creature->SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + 1, 3); m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Invisible = false; diff --git a/src/bindings/scripts/system.cpp b/src/bindings/scripts/system.cpp index e1e103f58e1..703fa139bee 100644 --- a/src/bindings/scripts/system.cpp +++ b/src/bindings/scripts/system.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * - * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> + * Thanks to the original authors: MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Dynamic/FactoryHolder.h b/src/framework/Dynamic/FactoryHolder.h index a9c7a718541..cf41be4953f 100644 --- a/src/framework/Dynamic/FactoryHolder.h +++ b/src/framework/Dynamic/FactoryHolder.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Dynamic/ObjectRegistry.h b/src/framework/Dynamic/ObjectRegistry.h index 25dfa9f5092..ef61ef38cde 100644 --- a/src/framework/Dynamic/ObjectRegistry.h +++ b/src/framework/Dynamic/ObjectRegistry.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/GameSystem/Grid.h b/src/framework/GameSystem/Grid.h index a239795f3c3..0210f62faf7 100644 --- a/src/framework/GameSystem/Grid.h +++ b/src/framework/GameSystem/Grid.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/GameSystem/GridLoader.h b/src/framework/GameSystem/GridLoader.h index 882974b81b0..df46585c225 100644 --- a/src/framework/GameSystem/GridLoader.h +++ b/src/framework/GameSystem/GridLoader.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/GameSystem/GridRefManager.h b/src/framework/GameSystem/GridRefManager.h index d233b844572..63e5065dc12 100644 --- a/src/framework/GameSystem/GridRefManager.h +++ b/src/framework/GameSystem/GridRefManager.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/GameSystem/GridReference.h b/src/framework/GameSystem/GridReference.h index 65592e780b1..529278ea036 100644 --- a/src/framework/GameSystem/GridReference.h +++ b/src/framework/GameSystem/GridReference.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/GameSystem/NGrid.h b/src/framework/GameSystem/NGrid.h index ecb20ff5069..6ed87624662 100644 --- a/src/framework/GameSystem/NGrid.h +++ b/src/framework/GameSystem/NGrid.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -76,12 +76,12 @@ class TRINITY_DLL_DECL NGrid const GridType& operator()(unsigned short x, unsigned short y) const { return i_cells[x][y]; } GridType& operator()(unsigned short x, unsigned short y) { return i_cells[x][y]; } - inline const uint32& GetGridId(void) const { return i_gridId; } - inline void SetGridId(const uint32 id) const { i_gridId = id; } - inline grid_state_t GetGridState(void) const { return i_cellstate; } - inline void SetGridState(grid_state_t s) { i_cellstate = s; } - inline int32 getX() const { return i_x; } - inline int32 getY() const { return i_y; } + const uint32& GetGridId(void) const { return i_gridId; } + void SetGridId(const uint32 id) const { i_gridId = id; } + grid_state_t GetGridState(void) const { return i_cellstate; } + void SetGridState(grid_state_t s) { i_cellstate = s; } + int32 getX() const { return i_x; } + int32 getY() const { return i_y; } void link(GridRefManager<NGrid<N, ACTIVE_OBJECT, WORLD_OBJECT_TYPES, GRID_OBJECT_TYPES, ThreadModel> >* pTo) { diff --git a/src/framework/GameSystem/TypeContainer.h b/src/framework/GameSystem/TypeContainer.h index b7949b8b461..e4a30103d2d 100644 --- a/src/framework/GameSystem/TypeContainer.h +++ b/src/framework/GameSystem/TypeContainer.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/GameSystem/TypeContainerFunctions.h b/src/framework/GameSystem/TypeContainerFunctions.h index 4dc1bcf79ba..ec005e2218c 100644 --- a/src/framework/GameSystem/TypeContainerFunctions.h +++ b/src/framework/GameSystem/TypeContainerFunctions.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/GameSystem/TypeContainerFunctionsPtr.h b/src/framework/GameSystem/TypeContainerFunctionsPtr.h index 33df2b1461c..5f15f6c65a7 100644 --- a/src/framework/GameSystem/TypeContainerFunctionsPtr.h +++ b/src/framework/GameSystem/TypeContainerFunctionsPtr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/GameSystem/TypeContainerVisitor.h b/src/framework/GameSystem/TypeContainerVisitor.h index c6999a88384..c544afa0f5e 100644 --- a/src/framework/GameSystem/TypeContainerVisitor.h +++ b/src/framework/GameSystem/TypeContainerVisitor.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Makefile.am b/src/framework/Makefile.am index 081b1cc9b44..e76e12ee76a 100644 --- a/src/framework/Makefile.am +++ b/src/framework/Makefile.am @@ -1,6 +1,6 @@ -# Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> # -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/src/framework/Network/SocketDefines.h b/src/framework/Network/SocketDefines.h index b5c0434c1d3..e18be535e91 100644 --- a/src/framework/Network/SocketDefines.h +++ b/src/framework/Network/SocketDefines.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Platform/CompilerDefs.h b/src/framework/Platform/CompilerDefs.h index cd7b6ff55bb..2bf7f7872f9 100644 --- a/src/framework/Platform/CompilerDefs.h +++ b/src/framework/Platform/CompilerDefs.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Platform/Define.h b/src/framework/Platform/Define.h index 5228359589b..574793a285d 100644 --- a/src/framework/Platform/Define.h +++ b/src/framework/Platform/Define.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 Mangos <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Policies/CreationPolicy.h b/src/framework/Policies/CreationPolicy.h index 72a7e265d62..10ed0109583 100644 --- a/src/framework/Policies/CreationPolicy.h +++ b/src/framework/Policies/CreationPolicy.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Policies/ObjectLifeTime.cpp b/src/framework/Policies/ObjectLifeTime.cpp index 15bcaa54686..55d452f801d 100644 --- a/src/framework/Policies/ObjectLifeTime.cpp +++ b/src/framework/Policies/ObjectLifeTime.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Policies/ObjectLifeTime.h b/src/framework/Policies/ObjectLifeTime.h index acd8516fc56..0666d7e19a8 100644 --- a/src/framework/Policies/ObjectLifeTime.h +++ b/src/framework/Policies/ObjectLifeTime.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,7 +34,7 @@ namespace Trinity class TRINITY_DLL_DECL ObjectLifeTime { public: - inline static void ScheduleCall(void (*destroyer)() ) + static void ScheduleCall(void (*destroyer)() ) { at_exit( destroyer ); } @@ -44,7 +44,7 @@ namespace Trinity }; template <class T> - inline void ObjectLifeTime<T>::OnDeadReference(void)// We don't handle Dead Reference for now + void ObjectLifeTime<T>::OnDeadReference(void) // We don't handle Dead Reference for now { throw std::runtime_error("Dead Reference"); } diff --git a/src/framework/Policies/Singleton.h b/src/framework/Policies/Singleton.h index 0f382197f1f..e33a52b2462 100644 --- a/src/framework/Policies/Singleton.h +++ b/src/framework/Policies/Singleton.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Policies/SingletonImp.h b/src/framework/Policies/SingletonImp.h index 16bfa2c4b05..386b321c1f1 100644 --- a/src/framework/Policies/SingletonImp.h +++ b/src/framework/Policies/SingletonImp.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Policies/ThreadingModel.h b/src/framework/Policies/ThreadingModel.h index 08d72854781..c482b2f10ad 100644 --- a/src/framework/Policies/ThreadingModel.h +++ b/src/framework/Policies/ThreadingModel.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Utilities/ByteConverter.h b/src/framework/Utilities/ByteConverter.h index 59081ef8ccd..c770be449cb 100644 --- a/src/framework/Utilities/ByteConverter.h +++ b/src/framework/Utilities/ByteConverter.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Utilities/Callback.h b/src/framework/Utilities/Callback.h index 29de60d998d..3b8c3e450f3 100644 --- a/src/framework/Utilities/Callback.h +++ b/src/framework/Utilities/Callback.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Utilities/CountedReference/Reference.h b/src/framework/Utilities/CountedReference/Reference.h index 693df05dddc..7954c437966 100644 --- a/src/framework/Utilities/CountedReference/Reference.h +++ b/src/framework/Utilities/CountedReference/Reference.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Utilities/CountedReference/ReferenceHolder.h b/src/framework/Utilities/CountedReference/ReferenceHolder.h index 0c2294fc8c5..03edff4c7cd 100644 --- a/src/framework/Utilities/CountedReference/ReferenceHolder.h +++ b/src/framework/Utilities/CountedReference/ReferenceHolder.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Utilities/CountedReference/ReferenceImpl.h b/src/framework/Utilities/CountedReference/ReferenceImpl.h index ef217a72dd9..43a01e2bc85 100644 --- a/src/framework/Utilities/CountedReference/ReferenceImpl.h +++ b/src/framework/Utilities/CountedReference/ReferenceImpl.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Utilities/EventProcessor.cpp b/src/framework/Utilities/EventProcessor.cpp index cd80a9effcc..d6e74ced42c 100644 --- a/src/framework/Utilities/EventProcessor.cpp +++ b/src/framework/Utilities/EventProcessor.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Utilities/EventProcessor.h b/src/framework/Utilities/EventProcessor.h index 508da2cc0fd..ecc7ec608be 100644 --- a/src/framework/Utilities/EventProcessor.h +++ b/src/framework/Utilities/EventProcessor.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Utilities/LinkedList.h b/src/framework/Utilities/LinkedList.h index 347fe7fa849..22a80f0b9ba 100644 --- a/src/framework/Utilities/LinkedList.h +++ b/src/framework/Utilities/LinkedList.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Utilities/LinkedReference/RefManager.h b/src/framework/Utilities/LinkedReference/RefManager.h index bfb163cc9c9..bef8b32862c 100644 --- a/src/framework/Utilities/LinkedReference/RefManager.h +++ b/src/framework/Utilities/LinkedReference/RefManager.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Utilities/LinkedReference/Reference.h b/src/framework/Utilities/LinkedReference/Reference.h index 28c77d918aa..5ca167a3948 100644 --- a/src/framework/Utilities/LinkedReference/Reference.h +++ b/src/framework/Utilities/LinkedReference/Reference.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,7 +44,7 @@ template <class TO, class FROM> class Reference : public LinkedListElement virtual ~Reference() {} // Create new link - inline void link(TO* toObj, FROM* fromObj) + void link(TO* toObj, FROM* fromObj) { assert(fromObj); // fromObj MUST not be NULL if(isValid()) @@ -59,16 +59,16 @@ template <class TO, class FROM> class Reference : public LinkedListElement // We don't need the reference anymore. Call comes from the refFrom object // Tell our refTo object, that the link is cut - inline void unlink() { targetObjectDestroyLink(); delink(); iRefTo = NULL; iRefFrom = NULL; } + void unlink() { targetObjectDestroyLink(); delink(); iRefTo = NULL; iRefFrom = NULL; } // Link is invalid due to destruction of referenced target object. Call comes from the refTo object // Tell our refFrom object, that the link is cut - inline void invalidate() // the iRefFrom MUST remain!! + void invalidate() // the iRefFrom MUST remain!! { sourceObjectDestroyLink(); delink(); iRefTo = NULL; } - inline bool isValid() const // Only check the iRefTo + bool isValid() const // Only check the iRefTo { return iRefTo != NULL; } @@ -83,10 +83,10 @@ template <class TO, class FROM> class Reference : public LinkedListElement Reference<TO,FROM> * nocheck_prev() { return((Reference<TO,FROM> *) LinkedListElement::nocheck_prev()); } Reference<TO,FROM> const * nocheck_prev() const { return((Reference<TO,FROM> const *) LinkedListElement::nocheck_prev()); } - inline TO* operator ->() const { return iRefTo; } - inline TO* getTarget() const { return iRefTo; } + TO* operator ->() const { return iRefTo; } + TO* getTarget() const { return iRefTo; } - inline FROM* getSource() const { return iRefFrom; } + FROM* getSource() const { return iRefFrom; } }; //===================================================== diff --git a/src/framework/Utilities/TypeList.h b/src/framework/Utilities/TypeList.h index daa6886467a..fc9f869aa2b 100644 --- a/src/framework/Utilities/TypeList.h +++ b/src/framework/Utilities/TypeList.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/framework/Utilities/UnorderedMap.h b/src/framework/Utilities/UnorderedMap.h index 31cd453ecba..13f9d58619b 100644 --- a/src/framework/Utilities/UnorderedMap.h +++ b/src/framework/Utilities/UnorderedMap.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/AccountMgr.cpp b/src/game/AccountMgr.cpp index d12f07e7bfd..d5d7ee1a59a 100644 --- a/src/game/AccountMgr.cpp +++ b/src/game/AccountMgr.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,11 +25,7 @@ #include "Policies/SingletonImp.h" #include "Util.h" -#ifdef DO_POSTGRESQL -extern DatabasePostgre LoginDatabase; -#else -extern DatabaseMysql LoginDatabase; -#endif +extern DatabaseType LoginDatabase; INSTANTIATE_SINGLETON_1(AccountMgr); diff --git a/src/game/AccountMgr.h b/src/game/AccountMgr.h index 0c1703ee2d9..a40c93989ed 100644 --- a/src/game/AccountMgr.h +++ b/src/game/AccountMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp new file mode 100644 index 00000000000..726316666c2 --- /dev/null +++ b/src/game/AchievementMgr.cpp @@ -0,0 +1,1177 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "AchievementMgr.h" +#include "Common.h" +#include "Player.h" +#include "WorldPacket.h" +#include "Database/DBCEnums.h" +#include "ObjectMgr.h" +#include "Guild.h" +#include "Database/DatabaseEnv.h" +#include "GameEvent.h" +#include "World.h" +#include "SpellMgr.h" +#include "ProgressBar.h" + +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1(AchievementGlobalMgr); + +const CriteriaCastSpellRequirement AchievementGlobalMgr::m_criteriaCastSpellRequirements[CRITERIA_CAST_SPELL_REQ_COUNT] = + { + {5272, 3057, 0, 0}, + {5273, 2784, 0, 0}, + {5752, 9099, 0, 0}, + {5753, 8403, 0, 0}, + {5772, 0, 0, RACE_GNOME}, + {5774, 0, 0, RACE_BLOODELF}, + {5775, 0, 0, RACE_DRAENEI}, + {5776, 0, 0, RACE_DWARF}, + {5777, 0, 0, RACE_HUMAN}, + {5778, 0, 0, RACE_NIGHTELF}, + {5779, 0, 0, RACE_ORC}, + {5780, 0, 0, RACE_TAUREN}, + {5781, 0, 0, RACE_TROLL}, + {5782, 0, 0, RACE_UNDEAD_PLAYER}, + {6225, 5661, 0, 0}, + {6226, 26044, 0, 0}, + {6228, 739, 0, 0}, + {6229, 927, 0, 0}, + {6230, 1444, 0, 0}, + {6231, 8140, 0, 0}, + {6232, 5489, 0, 0}, + {6233,12336, 0, 0}, + {6234, 1351, 0, 0}, + {6235, 5484, 0, 0}, + {6236, 1182, 0, 0}, + {6237, 0, CLASS_DEATH_KNIGHT, RACE_ORC}, + {6238, 0, CLASS_WARRIOR, RACE_HUMAN}, + {6239, 0, CLASS_SHAMAN, RACE_TAUREN}, + {6240, 0, CLASS_DRUID, RACE_NIGHTELF}, + {6241, 0, CLASS_ROGUE, RACE_UNDEAD_PLAYER}, + {6242, 0, CLASS_HUNTER, RACE_TROLL}, + {6243, 0, CLASS_MAGE, RACE_GNOME}, + {6244, 0, CLASS_PALADIN, RACE_DWARF}, + {6245, 0, CLASS_WARLOCK, RACE_BLOODELF}, + {6246, 0, CLASS_PRIEST, RACE_DRAENEI}, + {6312, 0, CLASS_WARLOCK, RACE_GNOME}, + {6313, 0, CLASS_DEATH_KNIGHT, RACE_HUMAN}, + {6314, 0, CLASS_PRIEST, RACE_NIGHTELF}, + {6315, 0, CLASS_SHAMAN, RACE_ORC}, + {6316, 0, CLASS_DRUID, RACE_TAUREN}, + {6317, 0, CLASS_ROGUE, RACE_TROLL}, + {6318, 0, CLASS_WARRIOR, RACE_UNDEAD_PLAYER}, + {6319, 0, CLASS_MAGE, RACE_BLOODELF}, + {6320, 0, CLASS_PALADIN, RACE_DRAENEI}, + {6321, 0, CLASS_HUNTER, RACE_DWARF}, + {6662, 31261, 0, 0} + }; + +AchievementMgr::AchievementMgr(Player *player) +{ + m_player = player; +} + +AchievementMgr::~AchievementMgr() +{ +} + +void AchievementMgr::Reset() +{ + for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); ++iter) + { + WorldPacket data(SMSG_ACHIEVEMENT_DELETED,4); + data << uint32(iter->first); + m_player->SendDirectMessage(&data); + } + + for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) + { + WorldPacket data(SMSG_CRITERIA_DELETED,4); + data << uint32(iter->first); + m_player->SendDirectMessage(&data); + } + + m_completedAchievements.clear(); + m_criteriaProgress.clear(); + DeleteFromDB(m_player->GetGUIDLow()); + + // re-fill data + CheckAllAchievementCriteria(); +} + +void AchievementMgr::DeleteFromDB(uint32 lowguid) +{ + CharacterDatabase.BeginTransaction (); + CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = %u",lowguid); + CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = %u",lowguid); + CharacterDatabase.CommitTransaction (); +} + +void AchievementMgr::SaveToDB() +{ + if(!m_completedAchievements.empty()) + { + bool need_execute = false; + std::ostringstream ssdel; + std::ostringstream ssins; + for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); ++iter) + { + if(!iter->second.changed) + continue; + + /// first new/changed record prefix + if(!need_execute) + { + ssdel << "DELETE FROM character_achievement WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND achievement IN ("; + ssins << "INSERT INTO character_achievement (guid, achievement, date) VALUES "; + need_execute = true; + } + /// next new/changed record prefix + else + { + ssdel << ", "; + ssins << ", "; + } + + // new/changed record data + ssdel << iter->first; + ssins << "("<<GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << uint64(iter->second.date) << ")"; + + /// mark as saved in db + iter->second.changed = false; + } + + if(need_execute) + ssdel << ")"; + + if(need_execute) + { + CharacterDatabase.BeginTransaction (); + CharacterDatabase.Execute( ssdel.str().c_str() ); + CharacterDatabase.Execute( ssins.str().c_str() ); + CharacterDatabase.CommitTransaction (); + } + } + + if(!m_criteriaProgress.empty()) + { + /// prepare deleting and insert + bool need_execute_del = false; + bool need_execute_ins = false; + std::ostringstream ssdel; + std::ostringstream ssins; + for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) + { + if(!iter->second.changed) + continue; + + // deleted data (including 0 progress state) + { + /// first new/changed record prefix (for any counter value) + if(!need_execute_del) + { + ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND criteria IN ("; + need_execute_del = true; + } + /// next new/changed record prefix + else + ssdel << ", "; + + // new/changed record data + ssdel << iter->first; + } + + // store data only for real progress + if(iter->second.counter != 0) + { + /// first new/changed record prefix + if(!need_execute_ins) + { + ssins << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES "; + need_execute_ins = true; + } + /// next new/changed record prefix + else + ssins << ", "; + + // new/changed record data + ssins << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second.counter << ", " << iter->second.date << ")"; + } + + /// mark as updated in db + iter->second.changed = false; + } + + if(need_execute_del) // DELETE ... IN (.... _)_ + ssdel << ")"; + + if(need_execute_del || need_execute_ins) + { + CharacterDatabase.BeginTransaction (); + if(need_execute_del) + CharacterDatabase.Execute( ssdel.str().c_str() ); + if(need_execute_ins) + CharacterDatabase.Execute( ssins.str().c_str() ); + CharacterDatabase.CommitTransaction (); + } + } +} + +void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult) +{ + if(achievementResult) + { + do + { + Field *fields = achievementResult->Fetch(); + CompletedAchievementData& ca = m_completedAchievements[fields[0].GetUInt32()]; + ca.date = time_t(fields[1].GetUInt64()); + ca.changed = false; + } while(achievementResult->NextRow()); + delete achievementResult; + } + + if(criteriaResult) + { + do + { + Field *fields = criteriaResult->Fetch(); + + uint32 id = fields[0].GetUInt32(); + uint32 counter = fields[1].GetUInt32(); + time_t date = time_t(fields[2].GetUInt64()); + + AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(id); + if(!criteria || criteria->timeLimit && date + criteria->timeLimit < time(NULL)) + continue; + + CriteriaProgress& progress = m_criteriaProgress[id]; + progress.counter = counter; + progress.date = date; + progress.changed = false; + } while(criteriaResult->NextRow()); + delete criteriaResult; + } + +} + +void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) +{ + sLog.outDebug("AchievementMgr::SendAchievementEarned(%u)", achievement->ID); + + const char *msg = "|Hplayer:$N|h[$N]|h has earned the achievement $a!"; + if(Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId())) + { + WorldPacket data(SMSG_MESSAGECHAT, 200); + data << uint8(CHAT_MSG_GUILD_ACHIEVEMENT); + data << uint32(LANG_UNIVERSAL); + data << uint64(GetPlayer()->GetGUID()); + data << uint32(5); + data << uint64(GetPlayer()->GetGUID()); + data << uint32(strlen(msg)+1); + data << msg; + data << uint8(0); + data << uint32(achievement->ID); + guild->BroadcastPacket(&data); + } + if(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL|ACHIEVEMENT_FLAG_REALM_FIRST_REACH)) + { + // broadcast realm first reached + WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, strlen(GetPlayer()->GetName())+1+8+4+4); + data << GetPlayer()->GetName(); + data << uint64(GetPlayer()->GetGUID()); + data << uint32(achievement->ID); + data << uint32(0); // 1=link supplied string as player name, 0=display plain string + sWorld.SendGlobalMessage(&data); + } + else + { + WorldPacket data(SMSG_MESSAGECHAT, 200); + data << uint8(CHAT_MSG_ACHIEVEMENT); + data << uint32(LANG_UNIVERSAL); + data << uint64(GetPlayer()->GetGUID()); + data << uint32(5); + data << uint64(GetPlayer()->GetGUID()); + data << uint32(strlen(msg)+1); + data << msg; + data << uint8(0); + data << uint32(achievement->ID); + GetPlayer()->SendMessageToSet(&data, true); + + } + WorldPacket data(SMSG_ACHIEVEMENT_EARNED, 8+4+8); + data.append(GetPlayer()->GetPackGUID()); + data << uint32(achievement->ID); + data << uint32(secsToTimeBitFields(time(NULL))); + data << uint32(0); + GetPlayer()->SendMessageToSet(&data, true); +} + +void AchievementMgr::SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress) +{ + WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8); + data << uint32(id); + + // the counter is packed like a packed Guid + data.appendPackGUID(progress->counter); + + data.append(GetPlayer()->GetPackGUID()); + data << uint32(0); + data << uint32(secsToTimeBitFields(progress->date)); + data << uint32(0); // timer 1 + data << uint32(0); // timer 2 + GetPlayer()->SendMessageToSet(&data, true); +} + +/** + * called at player login. The player might have fulfilled some achievements when the achievement system wasn't working yet + */ +void AchievementMgr::CheckAllAchievementCriteria() +{ + // suppress sending packets + for(uint32 i=0; i<ACHIEVEMENT_CRITERIA_TYPE_TOTAL; ++i) + UpdateAchievementCriteria(AchievementCriteriaTypes(i)); +} + +/** + * this function will be called whenever the user might have done a criteria relevant action + */ +void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, Unit *unit, uint32 time) +{ + sLog.outDetail("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time); + + if (!sWorld.getConfig(CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS) && m_player->GetSession()->GetSecurity() > SEC_PLAYER) + return; + + AchievementCriteriaEntryList const& achievementCriteriaList = achievementmgr.GetAchievementCriteriaByType(type); + for(AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i!=achievementCriteriaList.end(); ++i) + { + AchievementCriteriaEntry const *achievementCriteria = (*i); + + // don't update already completed criteria + if(IsCompletedCriteria(achievementCriteria)) + continue; + + if(achievementCriteria->groupFlag & ACHIEVEMENT_CRITERIA_GROUP_NOT_IN_GROUP && GetPlayer()->GetGroup()) + continue; + + AchievementEntry const *achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement); + if(!achievement) + continue; + + if(achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_HORDE && GetPlayer()->GetTeam() != HORDE || + achievement->factionFlag == ACHIEVEMENT_FACTION_FLAG_ALLIANCE && GetPlayer()->GetTeam() != ALLIANCE) + continue; + + switch (type) + { + case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: + SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel()); + break; + case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1); + break; + case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(achievementCriteria->kill_creature.creatureID != miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, miscvalue2, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: + if(uint32 skillvalue = GetPlayer()->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID)) + SetCriteriaProgress(achievementCriteria, skillvalue); + break; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT: + { + uint32 counter =0; + for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++) + if(itr->second.m_rewarded) + counter++; + SetCriteriaProgress(achievementCriteria, counter); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE: + { + uint32 counter =0; + for(QuestStatusMap::iterator itr = GetPlayer()->getQuestStatusMap().begin(); itr!=GetPlayer()->getQuestStatusMap().end(); itr++) + { + Quest const* quest = objmgr.GetQuestTemplate(itr->first); + if(itr->second.m_rewarded && quest->GetZoneOrSort() == achievementCriteria->complete_quests_in_zone.zoneID) + counter++; + } + SetCriteriaProgress(achievementCriteria, counter); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, miscvalue1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(GetPlayer()->GetMapId() != achievementCriteria->complete_battleground.mapID) + continue; + SetCriteriaProgress(achievementCriteria, miscvalue1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: + if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID)) + SetCriteriaProgress(achievementCriteria, 1); + break; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: + if(m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end()) + SetCriteriaProgress(achievementCriteria, 1); + break; + case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(GetPlayer()->GetMapId() != achievementCriteria->death_at_map.mapID) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(miscvalue1 != achievementCriteria->killed_by_creature.creatureEntry) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: + { + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(achievement->ID == 1260) + { + if(Player::GetDrunkenstateByValue(GetPlayer()->GetDrunkValue()) != DRUNKEN_SMASHED) + continue; + // TODO: hardcoding eventid is bad, it can differ from DB to DB - maye implement something using HolidayNames.dbc? + if(!gameeventmgr.IsActiveEvent(26)) + continue; + } + // miscvalue1 is the ingame fallheight*100 as stored in dbc + SetCriteriaProgress(achievementCriteria, miscvalue1); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: + if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID)) + SetCriteriaProgress(achievementCriteria, 1); + break; + case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: + // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case + if(!miscvalue1) + continue; + if(achievementCriteria->use_item.itemID != miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: + // speedup for non-login case + if(miscvalue1 && achievementCriteria->own_item.itemID!=miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetItemCount(achievementCriteria->own_item.itemID, true)); + break; + case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: + // You _have_ to loot that item, just owning it when logging in does _not_ count! + if(!miscvalue1) + continue; + if(miscvalue1 != achievementCriteria->own_item.itemID) + continue; + SetCriteriaProgress(achievementCriteria, miscvalue2, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: + if (!miscvalue1 || miscvalue1 != achievementCriteria->be_spell_target.spellID) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: + if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: + { + if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) + continue; + + // those requirements couldn't be found in the dbc + if (CriteriaCastSpellRequirement const* requirement = AchievementGlobalMgr::GetCriteriaCastSpellRequirement(achievementCriteria)) + { + if (!unit) + continue; + + if (requirement->creatureEntry && unit->GetEntry() != requirement->creatureEntry) + continue; + + if (requirement->playerRace && (unit->GetTypeId() != TYPEID_PLAYER || unit->getRace()!=requirement->playerRace)) + continue; + + if (requirement->playerClass && (unit->GetTypeId() != TYPEID_PLAYER || unit->getClass()!=requirement->playerClass)) + continue; + } + + SetCriteriaProgress(achievementCriteria, 1, true); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: + { + uint32 spellCount = 0; + for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin(); + spellIter != GetPlayer()->GetSpellMap().end(); + spellIter++) + { + for(SkillLineAbilityMap::const_iterator skillIter = spellmgr.GetBeginSkillLineAbilityMap(spellIter->first); + skillIter != spellmgr.GetEndSkillLineAbilityMap(spellIter->first); + skillIter++) + { + if(skillIter->second->skillId == achievementCriteria->learn_skilline_spell.skillLine) + spellCount++; + } + } + SetCriteriaProgress(achievementCriteria, spellCount); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: + { + // skip for login case + if(!miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, 1); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION: + { + int32 reputation = GetPlayer()->GetReputation(achievementCriteria->gain_reputation.factionID); + if (reputation > 0) + SetCriteriaProgress(achievementCriteria, reputation); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION: + { + uint32 counter = 0; + const FactionStateList factionStateList = GetPlayer()->GetFactionStateList(); + for (FactionStateList::const_iterator iter = factionStateList.begin(); iter!= factionStateList.end(); iter++) + { + if(GetPlayer()->ReputationToRank(iter->second.Standing) >= REP_EXALTED) + ++counter; + } + SetCriteriaProgress(achievementCriteria, counter); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: + { + WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference); + if(!worldOverlayEntry) + break; + + int32 exploreFlag = GetAreaFlagByAreaID(worldOverlayEntry->areatableID); + if(exploreFlag < 0) + break; + + uint32 playerIndexOffset = uint32(exploreFlag) / 32; + uint32 mask = 1<< (uint32(exploreFlag) % 32); + + if(GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask) + SetCriteriaProgress(achievementCriteria, 1); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: + case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: + { + // miscvalue1 = itemid + // miscvalue2 = diced value + if(!miscvalue1) + continue; + if(miscvalue2 != achievementCriteria->roll_greed_on_loot.rollValue) + continue; + ItemPrototype const *pProto = objmgr.GetItemPrototype( miscvalue1 ); + + uint32 requiredItemLevel = 0; + if (achievementCriteria->ID == 2412 || achievementCriteria->ID == 2358) + requiredItemLevel = 185; + + if(!pProto || pProto->ItemLevel <requiredItemLevel) + continue; + SetCriteriaProgress(achievementCriteria, 1, true); + break; + } + } + if(IsCompletedCriteria(achievementCriteria)) + CompletedCriteria(achievementCriteria); + } +} + +bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria) +{ + AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement); + if(!achievement) + return false; + + // counter can never complete + if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) + return false; + + if(achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) + { + // someone on this realm has already completed that achievement + if(achievementmgr.IsRealmCompleted(achievement)) + return false; + } + + CriteriaProgressMap::const_iterator itr = m_criteriaProgress.find(achievementCriteria->ID); + if(itr == m_criteriaProgress.end()) + return false; + + CriteriaProgress const* progress = &itr->second; + + switch(achievementCriteria->requiredType) + { + case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: + if(achievement->ID == 467 && GetPlayer()->getClass() != CLASS_SHAMAN || + achievement->ID == 466 && GetPlayer()->getClass() != CLASS_DRUID || + achievement->ID == 465 && GetPlayer()->getClass() != CLASS_PALADIN || + achievement->ID == 464 && GetPlayer()->getClass() != CLASS_PRIEST || + achievement->ID == 463 && GetPlayer()->getClass() != CLASS_WARLOCK || + achievement->ID == 462 && GetPlayer()->getClass() != CLASS_HUNTER || + achievement->ID == 461 && GetPlayer()->getClass() != CLASS_DEATH_KNIGHT || + achievement->ID == 460 && GetPlayer()->getClass() != CLASS_MAGE || + achievement->ID == 459 && GetPlayer()->getClass() != CLASS_WARRIOR || + achievement->ID == 458 && GetPlayer()->getClass() != CLASS_ROGUE || + + achievement->ID == 1404 && GetPlayer()->getRace() != RACE_GNOME || + achievement->ID == 1405 && GetPlayer()->getRace() != RACE_BLOODELF || + achievement->ID == 1406 && GetPlayer()->getRace() != RACE_DRAENEI || + achievement->ID == 1407 && GetPlayer()->getRace() != RACE_DWARF || + achievement->ID == 1408 && GetPlayer()->getRace() != RACE_HUMAN || + achievement->ID == 1409 && GetPlayer()->getRace() != RACE_NIGHTELF || + achievement->ID == 1410 && GetPlayer()->getRace() != RACE_ORC || + achievement->ID == 1411 && GetPlayer()->getRace() != RACE_TAUREN || + achievement->ID == 1412 && GetPlayer()->getRace() != RACE_TROLL || + achievement->ID == 1413 && GetPlayer()->getRace() != RACE_UNDEAD_PLAYER ) + return false; + return progress->counter >= achievementCriteria->reach_level.level; + case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: + return progress->counter >= achievementCriteria->buy_bank_slot.numberOfSlots; + case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: + return progress->counter >= achievementCriteria->kill_creature.creatureCount; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: + return progress->counter >= 1; + case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: + return progress->counter >= achievementCriteria->reach_skill_level.skillLevel; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT: + return progress->counter >= achievementCriteria->complete_quest_count.totalQuestCount; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE: + return progress->counter >= achievementCriteria->complete_quests_in_zone.questCount; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: + return progress->counter >= achievementCriteria->complete_daily_quest.questCount; + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: + return progress->counter >= 1; + case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: + return progress->counter >= achievementCriteria->fall_without_dying.fallHeight; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: + return progress->counter >= 1; + case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: + return progress->counter >= achievementCriteria->use_item.itemCount; + case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: + return progress->counter >= achievementCriteria->own_item.itemCount; + case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: + return progress->counter >= achievementCriteria->loot_item.itemCount; + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2: + return progress->counter >= achievementCriteria->be_spell_target.spellCount; + case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL: + case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: + return progress->counter >= achievementCriteria->cast_spell.castCount; + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: + return progress->counter >= achievementCriteria->learn_skilline_spell.spellCount; + case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: + return progress->counter >= achievementCriteria->visit_barber.numberOfVisits; + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION: + return progress->counter >= achievementCriteria->gain_reputation.reputationAmount; + case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION: + return progress->counter >= achievementCriteria->gain_exalted_reputation.numberOfExaltedFactions; + case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: + return progress->counter >= 1; + case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: + case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT: + return progress->counter >= achievementCriteria->roll_greed_on_loot.count; + + // handle all statistic-only criteria here + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: + case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP: + case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE: + case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: + return false; + } + return false; +} + +void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria) +{ + AchievementEntry const* achievement = sAchievementStore.LookupEntry(criteria->referredAchievement); + if(!achievement) + return; + // counter can never complete + if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) + return; + + if(criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL || GetAchievementCompletionState(achievement)==ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED) + { + CompletedAchievement(achievement); + } +} + +// TODO: achievement 705 requires 4 criteria to be fulfilled +AchievementCompletionState AchievementMgr::GetAchievementCompletionState(AchievementEntry const* entry) +{ + if(m_completedAchievements.find(entry->ID)!=m_completedAchievements.end()) + return ACHIEVEMENT_COMPLETED_COMPLETED_STORED; + + bool foundOutstanding = false; + for (uint32 entryId = 0; entryId<sAchievementCriteriaStore.GetNumRows(); entryId++) + { + AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId); + if(!criteria || criteria->referredAchievement!= entry->ID) + continue; + + if(IsCompletedCriteria(criteria) && criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL) + return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED; + + // found an umcompleted criteria, but DONT return false yet - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL + if(!IsCompletedCriteria(criteria)) + foundOutstanding = true; + } + if(foundOutstanding) + return ACHIEVEMENT_COMPLETED_NONE; + else + return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED; +} + +void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative) +{ + sLog.outDetail("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue); + CriteriaProgress *progress = NULL; + + CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID); + + if(iter == m_criteriaProgress.end()) + { + // not create record for 0 counter + if(newValue == 0) + return; + + progress = &m_criteriaProgress[entry->ID]; + progress->counter = newValue; + progress->date = time(NULL); + } + else + { + progress = &iter->second; + if(relative) + newValue += progress->counter; + + // not update (not mark as changed) if counter will have same value + if(progress->counter == newValue) + return; + + progress->counter = newValue; + } + + progress->changed = true; + + if(entry->timeLimit) + { + time_t now = time(NULL); + if(progress->date + entry->timeLimit < now) + { + progress->counter = 1; + } + // also it seems illogical, the timeframe will be extended at every criteria update + progress->date = now; + } + SendCriteriaUpdate(entry->ID,progress); +} + +void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) +{ + sLog.outDetail("AchievementMgr::CompletedAchievement(%u)", achievement->ID); + if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER || m_completedAchievements.find(achievement->ID)!=m_completedAchievements.end()) + return; + + SendAchievementEarned(achievement); + CompletedAchievementData& ca = m_completedAchievements[achievement->ID]; + ca.date = time(NULL); + ca.changed = true; + + // don't insert for ACHIEVEMENT_FLAG_REALM_FIRST_KILL since otherwise only the first group member would reach that achievement + // TODO: where do set this instead? + if(!(achievement->flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL)) + achievementmgr.SetRealmCompleted(achievement); + + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT); + + // reward items and titles if any + AchievementReward const* reward = achievementmgr.GetAchievementReward(achievement); + + // no rewards + if(!reward) + return; + + // titles + if(uint32 titleId = reward->titleId[GetPlayer()->GetTeam() == HORDE?0:1]) + { + if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId)) + GetPlayer()->SetTitle(titleEntry); + } + + // mail + if(reward->sender) + { + Item* item = reward->itemId ? Item::CreateItem(reward->itemId,1,GetPlayer ()) : NULL; + + MailItemsInfo mi; + if(item) + { + // save new item before send + item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted + + // item + mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item); + } + + int loc_idx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex(); + + // subject and text + std::string subject = reward->subject; + std::string text = reward->text; + if ( loc_idx >= 0 ) + { + if(AchievementRewardLocale const* loc = achievementmgr.GetAchievementRewardLocale(achievement)) + { + if (loc->subject.size() > size_t(loc_idx) && !loc->subject[loc_idx].empty()) + subject = loc->subject[loc_idx]; + if (loc->text.size() > size_t(loc_idx) && !loc->text[loc_idx].empty()) + text = loc->text[loc_idx]; + } + } + + uint32 itemTextId = objmgr.CreateItemText( text ); + + WorldSession::SendMailTo(GetPlayer(), MAIL_CREATURE, MAIL_STATIONERY_NORMAL, reward->sender, GetPlayer()->GetGUIDLow(), subject, itemTextId , &mi, 0, 0, MAIL_CHECK_MASK_NONE); + } +} + +void AchievementMgr::SendAllAchievementData() +{ + // since we don't know the exact size of the packed GUIDs this is just an approximation + WorldPacket data(SMSG_ALL_ACHIEVEMENT_DATA, 4*2+m_completedAchievements.size()*4*2+m_completedAchievements.size()*7*4); + BuildAllDataPacket(&data); + GetPlayer()->GetSession()->SendPacket(&data); +} + +void AchievementMgr::SendRespondInspectAchievements(Player* player) +{ + // since we don't know the exact size of the packed GUIDs this is just an approximation + WorldPacket data(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, 4+4*2+m_completedAchievements.size()*4*2+m_completedAchievements.size()*7*4); + data.append(GetPlayer()->GetPackGUID()); + BuildAllDataPacket(&data); + player->GetSession()->SendPacket(&data); +} + +/** + * used by both SMSG_ALL_ACHIEVEMENT_DATA and SMSG_RESPOND_INSPECT_ACHIEVEMENT + */ +void AchievementMgr::BuildAllDataPacket(WorldPacket *data) +{ + for(CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); ++iter) + { + *data << uint32(iter->first); + *data << uint32(secsToTimeBitFields(iter->second.date)); + } + *data << int32(-1); + + for(CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) + { + *data << uint32(iter->first); + data->appendPackGUID(iter->second.counter); + data->append(GetPlayer()->GetPackGUID()); + *data << uint32(0); + *data << uint32(secsToTimeBitFields(iter->second.date)); + *data << uint32(0); + *data << uint32(0); + } + + *data << int32(-1); +} + +//========================================================== +AchievementCriteriaEntryList const& AchievementGlobalMgr::GetAchievementCriteriaByType(AchievementCriteriaTypes type) +{ + return m_AchievementCriteriasByType[type]; +} + +void AchievementGlobalMgr::LoadAchievementCriteriaList() +{ + if(sAchievementCriteriaStore.GetNumRows()==0) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(""); + sLog.outErrorDb(">> Loaded 0 achievement criteria."); + return; + } + + barGoLink bar( sAchievementCriteriaStore.GetNumRows() ); + for (uint32 entryId = 0; entryId<sAchievementCriteriaStore.GetNumRows(); entryId++) + { + bar.step(); + + AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId); + if(!criteria) + continue; + + m_AchievementCriteriasByType[criteria->requiredType].push_back(criteria); + } + + sLog.outString(); + sLog.outString(">> Loaded %u achievement criteria.",m_AchievementCriteriasByType->size()); +} + + +void AchievementGlobalMgr::LoadCompletedAchievements() +{ + QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); + + if(!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(""); + sLog.outString(">> Loaded 0 realm completed achievements . DB table `character_achievement` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + do + { + bar.step(); + Field *fields = result->Fetch(); + m_allCompletedAchievements.insert(fields[0].GetUInt32()); + } while(result->NextRow()); + + delete result; + + sLog.outString(""); + sLog.outString(">> Loaded %u realm completed achievements.",m_allCompletedAchievements.size()); +} + +void AchievementGlobalMgr::LoadRewards() +{ + m_achievementRewards.clear(); // need for reload case + + // 0 1 2 3 4 5 6 + QueryResult *result = WorldDatabase.Query("SELECT entry, title_A, title_H, item, sender, subject, text FROM achievement_reward"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outErrorDb(">> Loaded 0 achievement rewards. DB table `achievement_reward` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + uint32 entry = fields[0].GetUInt32(); + if (!sAchievementStore.LookupEntry(entry)) + { + sLog.outErrorDb( "Table `achievement_reward` has wrong achievement (Entry: %u), ignore", entry); + continue; + } + + AchievementReward reward; + reward.titleId[0] = fields[1].GetUInt32(); + reward.titleId[1] = fields[2].GetUInt32(); + reward.itemId = fields[3].GetUInt32(); + reward.sender = fields[4].GetUInt32(); + reward.subject = fields[5].GetCppString(); + reward.text = fields[6].GetCppString(); + + if ((reward.titleId[0]==0)!=(reward.titleId[1]==0)) + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has title (A: %u H: %u) only for one from teams.", entry, reward.titleId[0], reward.titleId[1]); + + // must be title or mail at least + if (!reward.titleId[0] && !reward.titleId[1] && !reward.sender) + { + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have title or item reward data, ignore.", entry); + continue; + } + + if (reward.titleId[0]) + { + CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.titleId[0]); + if (!titleEntry) + { + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid title id (%u) in `title_A`, set to 0", entry, reward.titleId[0]); + reward.titleId[0] = 0; + } + } + + if (reward.titleId[1]) + { + CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.titleId[1]); + if (!titleEntry) + { + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid title id (%u) in `title_A`, set to 0", entry, reward.titleId[1]); + reward.titleId[1] = 0; + } + } + + //check mail data before item for report including wrong item case + if (reward.sender) + { + if (!objmgr.GetCreatureTemplate(reward.sender)) + { + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid creature entry %u as sender, mail reward skipped.", entry, reward.sender); + reward.sender = 0; + } + } + else + { + if (reward.itemId) + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have sender data but have item reward, item will not rewarded", entry); + + if (!reward.subject.empty()) + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have sender data but have mail subject.", entry); + + if (!reward.text.empty()) + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) not have sender data but have mail text.", entry); + } + + if (reward.itemId) + { + if (!objmgr.GetItemPrototype(reward.itemId)) + { + sLog.outErrorDb( "Table `achievement_reward` (Entry: %u) has invalid item id %u, reward mail will be without item.", entry, reward.itemId); + reward.itemId = 0; + } + } + + m_achievementRewards[entry] = reward; + + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u achievement reward locale strings", m_achievementRewardLocales.size() ); +} + +void AchievementGlobalMgr::LoadRewardLocales() +{ + m_achievementRewardLocales.clear(); // need for reload case + + QueryResult *result = WorldDatabase.Query("SELECT entry,subject_loc1,text_loc1,subject_loc2,text_loc2,subject_loc3,text_loc3,subject_loc4,text_loc4,subject_loc5,text_loc5,subject_loc6,text_loc6,subject_loc7,text_loc7,subject_loc8,text_loc8 FROM locales_achievement_reward"); + + if(!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(""); + sLog.outString(">> Loaded 0 achievement reward locale strings. DB table `locales_achievement_reward` is empty."); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + Field *fields = result->Fetch(); + bar.step(); + + uint32 entry = fields[0].GetUInt32(); + + if(m_achievementRewards.find(entry)==m_achievementRewards.end()) + { + sLog.outErrorDb( "Table `locales_achievement_reward` (Entry: %u) has locale strings for not existed achievement reward .", entry); + continue; + } + + AchievementRewardLocale& data = m_achievementRewardLocales[entry]; + + for(int i = 1; i < MAX_LOCALE; ++i) + { + std::string str = fields[1+2*(i-1)].GetCppString(); + if(!str.empty()) + { + int idx = objmgr.GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.subject.size() <= idx) + data.subject.resize(idx+1); + + data.subject[idx] = str; + } + } + str = fields[1+2*(i-1)+1].GetCppString(); + if(!str.empty()) + { + int idx = objmgr.GetOrNewIndexForLocale(LocaleConstant(i)); + if(idx >= 0) + { + if(data.text.size() <= idx) + data.text.resize(idx+1); + + data.text[idx] = str; + } + } + } + } while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u achievement reward locale strings", m_achievementRewardLocales.size() ); +} diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h new file mode 100644 index 00000000000..aadf1f16bd9 --- /dev/null +++ b/src/game/AchievementMgr.h @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __MANGOS_ACHIEVEMENTMGR_H +#define __MANGOS_ACHIEVEMENTMGR_H + +#include "Common.h" +#include "Policies/Singleton.h" +#include "Database/DBCEnums.h" +#include "Database/DBCStores.h" +#include "Database/DatabaseEnv.h" + +#include <map> +#include <string> + +#define CRITERIA_CAST_SPELL_REQ_COUNT 46 +#define ACHIEVEMENT_REWARD_COUNT 57 + +typedef std::list<const AchievementCriteriaEntry*> AchievementCriteriaEntryList; + +struct CriteriaProgress +{ + uint32 counter; + time_t date; + bool changed; +}; + +struct CriteriaCastSpellRequirement +{ + uint32 achievementCriteriaId; + uint32 creatureEntry; + uint8 playerClass; + uint8 playerRace; +}; + +struct AchievementReward +{ + uint32 titleId[2]; + uint32 itemId; + uint32 sender; + std::string subject; + std::string text; +}; + +typedef std::map<uint32,AchievementReward> AchievementRewards; + +struct AchievementRewardLocale +{ + std::vector<std::string> subject; + std::vector<std::string> text; +}; + +typedef std::map<uint32,AchievementRewardLocale> AchievementRewardLocales; + + +struct CompletedAchievementData +{ + time_t date; + bool changed; +}; + +typedef UNORDERED_MAP<uint32, CriteriaProgress> CriteriaProgressMap; +typedef UNORDERED_MAP<uint32, CompletedAchievementData> CompletedAchievementMap; + +class Unit; +class Player; +class WorldPacket; + +enum AchievementCompletionState +{ + ACHIEVEMENT_COMPLETED_NONE, + ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED, + ACHIEVEMENT_COMPLETED_COMPLETED_STORED, +}; + +class AchievementMgr +{ + public: + AchievementMgr(Player* pl); + ~AchievementMgr(); + + void Reset(); + static void DeleteFromDB(uint32 lowguid); + void LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult); + void SaveToDB(); + void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0); + void CheckAllAchievementCriteria(); + void SendAllAchievementData(); + void SendRespondInspectAchievements(Player* player); + Player* GetPlayer() { return m_player;} + + private: + void SendAchievementEarned(AchievementEntry const* achievement); + void SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress); + void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative=false); + void CompletedCriteria(AchievementCriteriaEntry const* entry); + void CompletedAchievement(AchievementEntry const* entry); + bool IsCompletedCriteria(AchievementCriteriaEntry const* entry); + AchievementCompletionState GetAchievementCompletionState(AchievementEntry const* entry); + void BuildAllDataPacket(WorldPacket *data); + + Player* m_player; + CriteriaProgressMap m_criteriaProgress; + CompletedAchievementMap m_completedAchievements; +}; + +class AchievementGlobalMgr +{ + public: + AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type); + + AchievementReward const* GetAchievementReward(AchievementEntry const* achievement) const + { + AchievementRewards::const_iterator iter = m_achievementRewards.find(achievement->ID); + return iter!=m_achievementRewards.end() ? &iter->second : NULL; + } + + AchievementRewardLocale const* GetAchievementRewardLocale(AchievementEntry const* achievement) const + { + AchievementRewardLocales::const_iterator iter = m_achievementRewardLocales.find(achievement->ID); + return iter!=m_achievementRewardLocales.end() ? &iter->second : NULL; + } + + static CriteriaCastSpellRequirement const * GetCriteriaCastSpellRequirement(AchievementCriteriaEntry const *achievementCriteria) + { + for (uint32 i=0; i < CRITERIA_CAST_SPELL_REQ_COUNT; ++i) + if (m_criteriaCastSpellRequirements[i].achievementCriteriaId == achievementCriteria->ID) + return &m_criteriaCastSpellRequirements[i]; + + return NULL; + } + + bool IsRealmCompleted(AchievementEntry const* achievement) const + { + return m_allCompletedAchievements.find(achievement->ID) != m_allCompletedAchievements.end(); + } + + void SetRealmCompleted(AchievementEntry const* achievement) + { + m_allCompletedAchievements.insert(achievement->ID); + } + + void LoadAchievementCriteriaList(); + void LoadCompletedAchievements(); + void LoadRewards(); + void LoadRewardLocales(); + private: + static const CriteriaCastSpellRequirement m_criteriaCastSpellRequirements[]; + + // store achievement criterias by type to speed up lookup + AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL]; + + typedef std::set<uint32> AllCompletedAchievements; + AllCompletedAchievements m_allCompletedAchievements; + + AchievementRewards m_achievementRewards; + AchievementRewardLocales m_achievementRewardLocales; +}; + +#define achievementmgr Trinity::Singleton<AchievementGlobalMgr>::Instance() + +#endif diff --git a/src/game/AddonHandler.cpp b/src/game/AddonHandler.cpp index 74bb4d9d6bc..1372f9c323c 100644 --- a/src/game/AddonHandler.cpp +++ b/src/game/AddonHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -66,63 +66,84 @@ bool AddonHandler::BuildAddonPacket(WorldPacket *Source, WorldPacket *Target) if (Source->rpos() + 4 > Source->size()) return false; - *Source >> TempValue; //get real size of the packed structure + *Source >> TempValue; // get real size of the packed structure // empty addon packet, nothing process, can't be received from real client if(!TempValue) return false; - AddonRealSize = TempValue; //temp value because ZLIB only excepts uLongf + AddonRealSize = TempValue; // temp value because ZLIB only excepts uLongf - CurrentPosition = Source->rpos(); //get the position of the pointer in the structure + CurrentPosition = Source->rpos(); // get the position of the pointer in the structure - AddOnPacked.resize(AddonRealSize); //resize target for zlib action + AddOnPacked.resize(AddonRealSize); // resize target for zlib action if (!uncompress(const_cast<uint8*>(AddOnPacked.contents()), &AddonRealSize, const_cast<uint8*>((*Source).contents() + CurrentPosition), (*Source).size() - CurrentPosition)!= Z_OK) { Target->Initialize(SMSG_ADDON_INFO); - while(AddOnPacked.rpos() < AddOnPacked.size()) + uint32 addonsCount; + AddOnPacked >> addonsCount; // addons count? + + for(uint32 i = 0; i < addonsCount; ++i) { - std::string AddonNames; - uint8 unk6; - uint32 crc, unk7; + std::string addonName; + uint8 enabled; + uint32 crc, unk2; // check next addon data format correctness - if(AddOnPacked.rpos()+1+4+4+1 > AddOnPacked.size()) + if(AddOnPacked.rpos()+1 > AddOnPacked.size()) return false; - AddOnPacked >> AddonNames; + AddOnPacked >> addonName; // recheck next addon data format correctness - if(AddOnPacked.rpos()+4+4+1 > AddOnPacked.size()) + if(AddOnPacked.rpos()+1+4+4 > AddOnPacked.size()) return false; - AddOnPacked >> crc >> unk7 >> unk6; + AddOnPacked >> enabled >> crc >> unk2; - //sLog.outDebug("ADDON: Name:%s CRC:%x Unknown1 :%x Unknown2 :%x", AddonNames.c_str(), crc, unk7, unk6); + sLog.outDebug("ADDON: Name: %s, Enabled: 0x%x, CRC: 0x%x, Unknown2: 0x%x", addonName.c_str(), enabled, crc, unk2); - *Target << (uint8)2; + uint8 state = (enabled ? 2 : 1); + *Target << uint8(state); - uint8 unk1 = 1; - *Target << (uint8)unk1; + uint8 unk1 = (enabled ? 1 : 0); + *Target << uint8(unk1); if (unk1) { - uint8 unk2 = crc != 0x1c776d01LL; //If addon is Standard addon CRC - *Target << (uint8)unk2; + uint8 unk2 = (crc != 0x4c1c776d); // If addon is Standard addon CRC + *Target << uint8(unk2); if (unk2) Target->append(tdata, sizeof(tdata)); - *Target << (uint32)0; + *Target << uint32(0); } - uint8 unk3 = 0; - *Target << (uint8)unk3; + uint8 unk3 = (enabled ? 0 : 1); + *Target << uint8(unk3); if (unk3) { - // String, 256 + // String, 256 (null terminated?) + *Target << uint8(0); } } + + uint32 unk4; + AddOnPacked >> unk4; + + uint32 count = 0; + *Target << uint32(count); + /*for(uint32 i = 0; i < count; ++i) + { + uint32 + string (16 bytes) + string (16 bytes) + uint32 + }*/ + + if(AddOnPacked.rpos() != AddOnPacked.size()) + sLog.outDebug("packet under read!"); } else { diff --git a/src/game/AddonHandler.h b/src/game/AddonHandler.h index 6a3b6d21c83..78305db42bd 100644 --- a/src/game/AddonHandler.h +++ b/src/game/AddonHandler.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp index 65dd1849217..441a526fd3b 100644 --- a/src/game/AggressorAI.cpp +++ b/src/game/AggressorAI.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/AggressorAI.h b/src/game/AggressorAI.h index e50a4c0ece3..ef8e081a30f 100644 --- a/src/game/AggressorAI.h +++ b/src/game/AggressorAI.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/AnimalRandomMovementGenerator.h b/src/game/AnimalRandomMovementGenerator.h index 8f467dfe632..86a70d0279a 100644 --- a/src/game/AnimalRandomMovementGenerator.h +++ b/src/game/AnimalRandomMovementGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp index 5f1dfdb93d7..3765d5e731a 100644 --- a/src/game/ArenaTeam.cpp +++ b/src/game/ArenaTeam.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -304,8 +304,11 @@ void ArenaTeam::Roster(WorldSession *session) { Player *pl = NULL; + uint8 unk308 = 0; + WorldPacket data(SMSG_ARENA_TEAM_ROSTER, 100); data << uint32(GetId()); // arena team id + data << uint8(unk308); // 308 unknown value but affect packet structure data << uint32(GetMembersSize()); // members count data << uint32(GetType()); // arena team type? @@ -313,18 +316,24 @@ void ArenaTeam::Roster(WorldSession *session) { pl = objmgr.GetPlayer(itr->guid); - data << uint64(itr->guid); // guid - data << uint8((pl ? 1 : 0)); // online flag - data << itr->name; // member name + data << uint64(itr->guid); // guid + data << uint8((pl ? 1 : 0)); // online flag + data << itr->name; // member name data << uint32((itr->guid == GetCaptain() ? 0 : 1));// captain flag 0 captain 1 member - data << uint8((pl ? pl->getLevel() : 0)); // unknown, level? - data << uint8(itr->Class); // class - data << uint32(itr->games_week); // played this week - data << uint32(itr->wins_week); // wins this week - data << uint32(itr->games_season); // played this season - data << uint32(itr->wins_season); // wins this season - data << uint32(itr->personal_rating); // personal rating + data << uint8((pl ? pl->getLevel() : 0)); // unknown, level? + data << uint8(itr->Class); // class + data << uint32(itr->games_week); // played this week + data << uint32(itr->wins_week); // wins this week + data << uint32(itr->games_season); // played this season + data << uint32(itr->wins_season); // wins this season + data << uint32(itr->personal_rating); // personal rating + if(unk308) + { + data << float(0.0); // 308 unk + data << float(0.0); // 308 unk + } } + session->SendPacket(&data); sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_ROSTER"); } @@ -641,6 +650,19 @@ void ArenaTeam::FinishWeek() } } +bool ArenaTeam::IsFighting() const +{ + for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + { + if (Player *p = objmgr.GetPlayer(itr->guid)) + { + if (p->GetMap()->IsBattleArena()) + return true; + } + } + return false; +} + /* arenateam fields (id from 2.3.3 client): 1414 - arena team id 2v2 diff --git a/src/game/ArenaTeam.h b/src/game/ArenaTeam.h index 3c6972cdcd0..4b839401e12 100644 --- a/src/game/ArenaTeam.h +++ b/src/game/ArenaTeam.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -179,18 +179,7 @@ class ArenaTeam return NULL; } - bool IsFighting() const - { - for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) - { - if (Player *p = objmgr.GetPlayer(itr->guid)) - { - if (p->GetMap()->IsBattleArena()) - return true; - } - } - return false; - } + bool IsFighting() const; bool LoadArenaTeamFromDB(uint32 ArenaTeamId); void LoadMembersFromDB(uint32 ArenaTeamId); diff --git a/src/game/ArenaTeamHandler.cpp b/src/game/ArenaTeamHandler.cpp index d2c9f54d04b..56c9a219a73 100644 --- a/src/game/ArenaTeamHandler.cpp +++ b/src/game/ArenaTeamHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -173,7 +173,7 @@ void WorldSession::HandleArenaTeamInviteAcceptOpcode(WorldPacket & /*recv_data*/ if(!at) return; - if(_player->GetArenaTeamIdFromDB(_player->GetGUIDLow(), at->GetType())) + if(_player->GetArenaTeamId(at->GetSlot())) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ALREADY_IN_ARENA_TEAM); // already in arena team that size return; diff --git a/src/game/AuctionHouse.cpp b/src/game/AuctionHouse.cpp index c200c9751a6..b9bafdf0eb6 100644 --- a/src/game/AuctionHouse.cpp +++ b/src/game/AuctionHouse.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -55,21 +55,21 @@ void WorldSession::HandleAuctionHelloOpcode( WorldPacket & recv_data ) SendAuctionHello(guid, unit); } -static uint8 AuctioneerFactionToLocation(uint32 faction) +static AuctionLocation AuctioneerFactionToLocation(uint32 faction) { if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) - return 7; // neutral + return AUCTION_NEUTRAL; FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(faction); if(!u_entry) - return 7; // neutral + return AUCTION_NEUTRAL; if(u_entry->ourMask & FACTION_MASK_ALLIANCE) - return 2; + return AUCTION_ALLIANCE; else if(u_entry->ourMask & FACTION_MASK_HORDE) - return 6; + return AUCTION_HORDE; else - return 7; + return AUCTION_NEUTRAL; } //this void causes that auction window is opened @@ -132,13 +132,13 @@ void WorldSession::SendAuctionCommandResult(uint32 auctionId, uint32 Action, uin void WorldSession::SendAuctionBidderNotification( uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template) { WorldPacket data(SMSG_AUCTION_BIDDER_NOTIFICATION, (8*4)); - data << location; - data << auctionId; - data << (uint64) bidder; - data << bidSum; - data << (uint32) diff; - data << item_template; - data << (uint32) 0; + data << uint32(location); + data << uint32(auctionId); + data << uint64(bidder); + data << uint32(bidSum); + data << uint32(diff); + data << uint32(item_template); + data << uint32(0); SendPacket(&data); } @@ -268,7 +268,7 @@ void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data ) return; } - uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); + AuctionLocation location = AuctioneerFactionToLocation(pCreature->getFaction()); AuctionHouseObject * mAuctions; mAuctions = objmgr.GetAuctionsMap( location ); @@ -347,7 +347,7 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); + AuctionLocation location = AuctioneerFactionToLocation(pCreature->getFaction()); AuctionHouseObject * mAuctions; mAuctions = objmgr.GetAuctionsMap( location ); @@ -474,7 +474,7 @@ void WorldSession::HandleAuctionRemoveItem( WorldPacket & recv_data ) if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); + AuctionLocation location = AuctioneerFactionToLocation(pCreature->getFaction()); AuctionHouseObject * mAuctions; mAuctions = objmgr.GetAuctionsMap( location ); @@ -562,7 +562,7 @@ void WorldSession::HandleAuctionListBidderItems( WorldPacket & recv_data ) if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); + AuctionLocation location = AuctioneerFactionToLocation(pCreature->getFaction()); AuctionHouseObject* mAuctions = objmgr.GetAuctionsMap( location ); WorldPacket data( SMSG_AUCTION_BIDDER_LIST_RESULT, (4+4+4) ); @@ -582,7 +582,7 @@ void WorldSession::HandleAuctionListBidderItems( WorldPacket & recv_data ) ++count; } } - for (AuctionHouseObject::AuctionEntryMap::iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr) + for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr) { AuctionEntry *Aentry = itr->second; if( Aentry && Aentry->bidder == pl->GetGUIDLow() ) @@ -620,7 +620,7 @@ void WorldSession::HandleAuctionListOwnerItems( WorldPacket & recv_data ) if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); + AuctionLocation location = AuctioneerFactionToLocation(pCreature->getFaction()); AuctionHouseObject* mAuctions = objmgr.GetAuctionsMap( location ); @@ -629,7 +629,7 @@ void WorldSession::HandleAuctionListOwnerItems( WorldPacket & recv_data ) uint32 count = 0; uint32 totalcount = 0; - for (AuctionHouseObject::AuctionEntryMap::iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr) + for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr) { AuctionEntry *Aentry = itr->second; if( Aentry && Aentry->owner == _player->GetGUIDLow() ) @@ -650,9 +650,9 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8+4+1+1+1+4+4+4+4+1); - std::string searchedname, name; - uint8 levelmin, levelmax, usable, location; - uint32 count, totalcount, listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality; + std::string searchedname; + uint8 levelmin, levelmax, usable; + uint32 listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality; uint64 guid; recv_data >> guid; @@ -677,15 +677,14 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - location = AuctioneerFactionToLocation(pCreature->getFaction()); - AuctionHouseObject * mAuctions; - mAuctions = objmgr.GetAuctionsMap( location ); + AuctionLocation location = AuctioneerFactionToLocation(pCreature->getFaction()); + AuctionHouseObject * mAuctions = objmgr.GetAuctionsMap( location ); //sLog.outDebug("Auctionhouse search guid: " I64FMTD ", list from: %u, searchedname: %s, levelmin: %u, levelmax: %u, auctionSlotID: %u, auctionMainCategory: %u, auctionSubCategory: %u, quality: %u, usable: %u", guid, listfrom, searchedname.c_str(), levelmin, levelmax, auctionSlotID, auctionMainCategory, auctionSubCategory, quality, usable); WorldPacket data( SMSG_AUCTION_LIST_RESULT, (4+4+4) ); - count = 0; - totalcount = 0; + uint32 count = 0; + uint32 totalcount = 0; data << (uint32) 0; // converting string that we try to find to lower case @@ -695,7 +694,7 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) wstrToLower(wsearchedname); - for (AuctionHouseObject::AuctionEntryMap::iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr) + for (AuctionHouseObject::AuctionEntryMap::const_iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr) { AuctionEntry *Aentry = itr->second; Item *item = objmgr.GetAItem(Aentry->item_guidlow); @@ -716,7 +715,7 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) { if( ( levelmin == (0x00) || proto->RequiredLevel >= levelmin ) && ( levelmax == (0x00) || proto->RequiredLevel <= levelmax ) ) { - name = proto->Name1; + std::string name = proto->Name1; // local name int loc_idx = GetSessionDbLocaleIndex(); @@ -756,3 +755,23 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data ) data << (uint32) 300; // unk 2.3.0 const? SendPacket(&data); } + +void WorldSession::HandleAuctionListPendingSales( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_AUCTION_LIST_PENDING_SALES"); + recv_data.hexlike(); + + uint32 count = 0; + + WorldPacket data(SMSG_AUCTION_LIST_PENDING_SALES, 4); + data << uint32(count); // count + /*for(uint32 i = 0; i < count; ++i) + { + data << ""; // string + data << ""; // string + data << uint32(0); + data << uint32(0); + data << float(0); + }*/ + SendPacket(&data); +} diff --git a/src/game/AuctionHouseBot.cpp b/src/game/AuctionHouseBot.cpp index f05d31abb41..4830dcefce4 100644 --- a/src/game/AuctionHouseBot.cpp +++ b/src/game/AuctionHouseBot.cpp @@ -1,4 +1,3 @@ -#include "AuctionHouseBot.h" #include "Bag.h" #include "Config/ConfigEnv.h" #include "Database/DatabaseEnv.h" @@ -9,6 +8,7 @@ #include "World.h" #include "WorldSession.h" #include "time.h" +#include "AuctionHouseBot.h" #include <vector> #include <iostream> @@ -40,9 +40,9 @@ static bool Bind_When_Equipped = 0; static bool Bind_When_Use = 0; static bool Bind_Quest_Item = 0; -static AHBConfig AllianceConfig = AHBConfig(2); -static AHBConfig HordeConfig = AHBConfig(6); -static AHBConfig NeutralConfig = AHBConfig(7); +static AHBConfig AllianceConfig = AHBConfig(AUCTION_ALLIANCE); +static AHBConfig HordeConfig = AHBConfig(AUCTION_HORDE); +static AHBConfig NeutralConfig = AHBConfig(AUCTION_NEUTRAL); time_t _lastrun_a; time_t _lastrun_h; time_t _lastrun_n; @@ -905,18 +905,18 @@ void AuctionHouseBotInit() sLog.outString("AuctionHouseBot now includes AHBuyer by Kerbe and Paradox"); } -void AuctionHouseBotCommands(uint32 command, uint32 ahMapID, uint32 col, char* args) +void AuctionHouseBotCommands(uint32 command, AuctionLocation ahMapID, uint32 col, char* args) { AHBConfig *config; switch (ahMapID) { - case 2: + case AUCTION_ALLIANCE: config = &AllianceConfig; break; - case 6: + case AUCTION_HORDE: config = &HordeConfig; break; - case 7: + case AUCTION_NEUTRAL: config = &NeutralConfig; break; } diff --git a/src/game/AuctionHouseBot.h b/src/game/AuctionHouseBot.h index 71b14d17a4a..afb3e15e968 100644 --- a/src/game/AuctionHouseBot.h +++ b/src/game/AuctionHouseBot.h @@ -3,6 +3,7 @@ #include "Common.h" #include "Log.h" #include "Config/ConfigEnv.h" +#include "AuctionHouseObject.h" #define AHB_GREY 0 #define AHB_WHITE 1 #define AHB_GREEN 2 @@ -27,7 +28,7 @@ class AHBConfig { private: - uint32 AHID; + AuctionLocation AHID; uint32 minItems; uint32 maxItems; uint32 minTime; @@ -78,14 +79,14 @@ class AHBConfig uint32 bip; uint32 pip; public: - AHBConfig(uint32 ahid) + AHBConfig(AuctionLocation ahid) { AHID = ahid; } AHBConfig() { } - uint32 GetAHID() + AuctionLocation GetAHID() { return AHID; } @@ -683,5 +684,5 @@ class AHBConfig void AuctionHouseBot(); void AuctionHouseBotInit(); void AuctionHouseBotLoadValues(AHBConfig*); -void AuctionHouseBotCommands(uint32, uint32, uint32, char*); +void AuctionHouseBotCommands(uint32, AuctionLocation, uint32, char*); #endif diff --git a/src/game/AuctionHouseObject.h b/src/game/AuctionHouseObject.h index cccba8413da..f82867c5742 100644 --- a/src/game/AuctionHouseObject.h +++ b/src/game/AuctionHouseObject.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +41,15 @@ enum AuctionAction AUCTION_PLACE_BID = 2 }; +enum AuctionLocation +{ + AUCTION_ALLIANCE = 2, + AUCTION_HORDE = 6, + AUCTION_NEUTRAL = 7 +}; + +inline bool IsValidAuctionLocation(uint32 loc) { return loc == AUCTION_ALLIANCE || loc == AUCTION_HORDE || loc == AUCTION_NEUTRAL; } + struct AuctionEntry { uint32 Id; @@ -54,7 +63,7 @@ struct AuctionEntry time_t time; uint32 bidder; uint32 deposit; //deposit can be calculated only when creating auction - uint32 location; + AuctionLocation location; }; //this class is used as auctionhouse instance @@ -84,20 +93,12 @@ class AuctionHouseObject AuctionEntry* GetAuction(uint32 id) const { AuctionEntryMap::const_iterator itr = AuctionsMap.find( id ); - if( itr != AuctionsMap.end() ) - return itr->second; - return NULL; + return itr != AuctionsMap.end() ? itr->second : NULL; } bool RemoveAuction(uint32 id) { - AuctionEntryMap::iterator i = AuctionsMap.find(id); - if (i == AuctionsMap.end()) - { - return false; - } - AuctionsMap.erase(i); - return true; + return AuctionsMap.erase(id) ? true : false; } private: diff --git a/src/game/Bag.cpp b/src/game/Bag.cpp index 765d40f3962..1293b058d00 100644 --- a/src/game/Bag.cpp +++ b/src/game/Bag.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,7 +34,7 @@ Bag::Bag( ): Item() m_valuesCount = CONTAINER_END; - memset(m_bagslot, 0, sizeof(Item *) * MAX_BAG_SIZE); // Maximum 20 Slots + memset(m_bagslot, 0, sizeof(Item *) * MAX_BAG_SIZE); } Bag::~Bag() diff --git a/src/game/Bag.h b/src/game/Bag.h index 97f06917485..6f38057b4ce 100644 --- a/src/game/Bag.h +++ b/src/game/Bag.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index d392f074600..cb122fddbcf 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,7 @@ #include "Object.h" #include "Player.h" #include "BattleGround.h" +#include "BattleGroundMgr.h" #include "Creature.h" #include "MapManager.h" #include "Language.h" @@ -28,11 +29,14 @@ #include "SpellAuras.h" #include "ArenaTeam.h" #include "World.h" +#include "Group.h" +#include "ObjectMgr.h" +#include "WorldPacket.h" #include "Util.h" BattleGround::BattleGround() { - m_TypeID = 0; + m_TypeID = BattleGroundTypeId(0); m_InstanceID = 0; m_Status = 0; m_EndTime = 0; @@ -120,7 +124,7 @@ BattleGround::~BattleGround() this->RemoveFromBGFreeSlotQueue(); } -void BattleGround::Update(time_t diff) +void BattleGround::Update(uint32 diff) { if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) //BG is empty @@ -161,8 +165,6 @@ void BattleGround::Update(time_t diff) m_RemovedPlayers.clear(); } - // this code isn't efficient and its idea isn't implemented yet - /* offline players are removed from battleground in worldsession::LogoutPlayer() // remove offline players from bg after ~5 minutes if(GetPlayersSize()) { @@ -177,7 +179,7 @@ void BattleGround::Update(time_t diff) if(itr->second.LastOnlineTime >= MAX_OFFLINE_TIME) // 5 minutes m_RemovedPlayers[itr->first] = 1; // add to remove list (BG) } - }*/ + } m_LastResurrectTime += diff; if (m_LastResurrectTime >= RESURRECTION_INTERVAL) @@ -573,9 +575,10 @@ void BattleGround::EndBattleGround(uint32 winner) sBattleGroundMgr.BuildPvpLogDataPacket(&data, this); plr->GetSession()->SendPacket(&data); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); plr->GetSession()->SendPacket(&data); + plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1); } if(isArena() && isRated() && winner_arena_team && loser_arena_team) @@ -593,7 +596,7 @@ void BattleGround::EndBattleGround(uint32 winner) } // inform invited players about the removal - sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); + sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); if(Source) { @@ -788,8 +791,8 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac { if(!team) team = plr->GetTeam(); - uint32 bgTypeId = GetTypeID(); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); + BattleGroundTypeId bgTypeId = GetTypeID(); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); // if arena, remove the specific arena auras if(isArena()) { @@ -865,9 +868,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac plr->SetBGTeam(0); if(Transport) - { - plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO()); - } + plr->TeleportTo(plr->GetBattleGroundEntryPoint()); // Log sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName()); @@ -975,7 +976,7 @@ void BattleGround::AddPlayer(Player *plr) } (plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT); } - else + else (plr)->SetTemporaryUnsummonedPetNumber(0); if(GetStatus() == STATUS_WAIT_JOIN) // not started yet @@ -1178,7 +1179,8 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float // and when loading it (in go::LoadFromDB()), a new guid would be assigned to the object, and a new object would be created // so we must create it specific for this instance GameObject * go = new GameObject; - if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1)) + if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry, map, + PHASEMASK_NORMAL, x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1)) { sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry); sLog.outError("Cannot create gameobject template %u! BattleGround not created!", entry); @@ -1301,7 +1303,7 @@ Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, f return NULL; Creature* pCreature = new Creature; - if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, entry, teamval)) + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, PHASEMASK_NORMAL, entry, teamval)) { sLog.outError("Can't create creature entry: %u",entry); delete pCreature; @@ -1357,6 +1359,9 @@ void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime) */ bool BattleGround::DelCreature(uint32 type) { + if(!m_BgCreatures[type]) + return true; + Creature *cr = HashMapHolder<Creature>::Find(m_BgCreatures[type]); if(!cr) { @@ -1372,6 +1377,9 @@ bool BattleGround::DelCreature(uint32 type) bool BattleGround::DelObject(uint32 type) { + if(!m_BgObjects[type]) + return true; + GameObject *obj = HashMapHolder<GameObject>::Find(m_BgObjects[type]); if(!obj) { @@ -1405,10 +1413,12 @@ bool BattleGround::AddSpiritGuide(uint32 type, float x, float y, float z, float pCreature->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, pCreature->GetGUID()); // aura - pCreature->SetUInt32Value(UNIT_FIELD_AURA, SPELL_SPIRIT_HEAL_CHANNEL); - pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009); - pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C); - pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF); + //TODO: Fix display here + //pCreature->SetVisibleAura(0, SPELL_SPIRIT_HEAL_CHANNEL); + + //pCreature->SetUInt32Value(UNIT_FIELD_AURAFLAGS, 0x00000009); + //pCreature->SetUInt32Value(UNIT_FIELD_AURALEVELS, 0x0000003C); + //pCreature->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS, 0x000000FF); // casting visual effect pCreature->SetUInt32Value(UNIT_CHANNEL_SPELL, SPELL_SPIRIT_HEAL_CHANNEL); // correct cast speed @@ -1440,7 +1450,7 @@ void BattleGround::EndNow() SetStatus(STATUS_WAIT_LEAVE); SetEndTime(TIME_TO_AUTOREMOVE); // inform invited players about the removal - sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); + sBattleGroundMgr.m_BattleGroundQueues[BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); } // Battleground messages are localized using the dbc lang, they are not client language dependent @@ -1529,6 +1539,31 @@ uint32 BattleGround::GetPlayerTeam(uint64 guid) return 0; } +bool BattleGround::IsPlayerInBattleGround(uint64 guid) +{ + std::map<uint64, BattleGroundPlayer>::const_iterator itr = m_Players.find(guid); + if(itr!=m_Players.end()) + return true; + return false; +} + +void BattleGround::PlayerRelogin(Player* plr) +{ + if(GetStatus() != STATUS_WAIT_LEAVE) + return; + + WorldPacket data; + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(GetTypeID(), GetArenaType()); + + BlockMovement(plr); + + sBattleGroundMgr.BuildPvpLogDataPacket(&data, this); + plr->GetSession()->SendPacket(&data); + + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); + plr->GetSession()->SendPacket(&data); +} + uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const { int count = 0; @@ -1564,3 +1599,11 @@ int32 BattleGround::GetObjectType(uint64 guid) void BattleGround::HandleKillUnit(Creature *creature, Player *killer) { } + +void BattleGround::SetBgRaid( uint32 TeamID, Group *bg_raid ) +{ + Group* &old_raid = TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; + if(old_raid) old_raid->SetBattlegroundGroup(NULL); + if(bg_raid) bg_raid->SetBattlegroundGroup(this); + old_raid = bg_raid; +} diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index d1d9cb19f28..e6ab5f1359c 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,13 +22,16 @@ #define __BATTLEGROUND_H #include "Common.h" -#include "WorldPacket.h" -#include "WorldSession.h" -#include "Opcodes.h" -#include "ObjectMgr.h" -#include "BattleGroundMgr.h" #include "SharedDefines.h" +class Creature; +class GameObject; +class Group; +class Player; +class WorldPacket; + +struct WorldSafeLocsEntry; + enum BattleGroundSounds { SOUND_HORDE_WINS = 8454, @@ -132,20 +135,6 @@ struct BattleGroundObjectInfo uint32 spellid; }; -#define MAX_QUEUED_PLAYERS_MAP 7 - -enum BattleGroundTypeId -{ - BATTLEGROUND_AV = 1, - BATTLEGROUND_WS = 2, - BATTLEGROUND_AB = 3, - BATTLEGROUND_NA = 4, - BATTLEGROUND_BE = 5, - BATTLEGROUND_AA = 6, - BATTLEGROUND_EY = 7, - BATTLEGROUND_RL = 8 -}; - // handle the queue types and bg types separately to enable joining queue for different sized arenas at the same time enum BattleGroundQueueTypeId { @@ -153,9 +142,10 @@ enum BattleGroundQueueTypeId BATTLEGROUND_QUEUE_WS = 2, BATTLEGROUND_QUEUE_AB = 3, BATTLEGROUND_QUEUE_EY = 4, - BATTLEGROUND_QUEUE_2v2 = 5, - BATTLEGROUND_QUEUE_3v3 = 6, - BATTLEGROUND_QUEUE_5v5 = 7, + BATTLEGROUND_QUEUE_SA = 5, + BATTLEGROUND_QUEUE_2v2 = 6, + BATTLEGROUND_QUEUE_3v3 = 7, + BATTLEGROUND_QUEUE_5v5 = 8, }; enum ScoreType @@ -262,7 +252,7 @@ class BattleGround BattleGround(); /*BattleGround(const BattleGround& bg);*/ virtual ~BattleGround(); - virtual void Update(time_t diff); // must be implemented in BG subclass of BG specific update code, but must in begginning call parent version + virtual void Update(uint32 diff); // must be implemented in BG subclass of BG specific update code, but must in begginning call parent version virtual bool SetupBattleGround() // must be implemented in BG subclass { return true; @@ -275,7 +265,7 @@ class BattleGround /* Battleground */ // Get methods: char const* GetName() const { return m_Name; } - uint32 GetTypeID() const { return m_TypeID; } + BattleGroundTypeId GetTypeID() const { return m_TypeID; } uint32 GetQueueType() const { return m_Queue_type; } uint32 GetInstanceID() const { return m_InstanceID; } uint32 GetStatus() const { return m_Status; } @@ -298,7 +288,7 @@ class BattleGround // Set methods: void SetName(char const* Name) { m_Name = Name; } - void SetTypeID(uint32 TypeID) { m_TypeID = TypeID; } + void SetTypeID(BattleGroundTypeId TypeID) { m_TypeID = TypeID; } void SetQueueType(uint32 ID) { m_Queue_type = ID; } void SetInstanceID(uint32 InstanceID) { m_InstanceID = InstanceID; } void SetStatus(uint32 Status) { m_Status = Status; } @@ -395,13 +385,7 @@ class BattleGround /* Raid Group */ Group *GetBgRaid(uint32 TeamID) const { return TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; } - void SetBgRaid(uint32 TeamID, Group *bg_raid) - { - Group* &old_raid = TeamID == ALLIANCE ? m_BgRaids[BG_TEAM_ALLIANCE] : m_BgRaids[BG_TEAM_HORDE]; - if(old_raid) old_raid->SetBattlegroundGroup(NULL); - if(bg_raid) bg_raid->SetBattlegroundGroup(this); - old_raid = bg_raid; - } + void SetBgRaid(uint32 TeamID, Group *bg_raid); virtual void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); @@ -468,6 +452,8 @@ class BattleGround // since arenas can be AvA or Hvh, we have to get the "temporary" team of a player uint32 GetPlayerTeam(uint64 guid); + bool IsPlayerInBattleGround(uint64 guid); + void PlayerRelogin(Player* plr); void SetDeleteThis() {m_SetDeleteThis = true;} @@ -496,7 +482,7 @@ class BattleGround BGHonorMode m_HonorMode; private: /* Battleground */ - uint32 m_TypeID; //Battleground type, defined in enum BattleGroundTypeId + BattleGroundTypeId m_TypeID; uint32 m_InstanceID; //BattleGround Instance's GUID! uint32 m_Status; uint32 m_StartTime; diff --git a/src/game/BattleGroundAA.cpp b/src/game/BattleGroundAA.cpp index 8737088894a..fa7a90014ef 100644 --- a/src/game/BattleGroundAA.cpp +++ b/src/game/BattleGroundAA.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,7 +32,7 @@ BattleGroundAA::~BattleGroundAA() } -void BattleGroundAA::Update(time_t diff) +void BattleGroundAA::Update(uint32 diff) { BattleGround::Update(diff); } diff --git a/src/game/BattleGroundAA.h b/src/game/BattleGroundAA.h index edddc110600..3d4dad0be9a 100644 --- a/src/game/BattleGroundAA.h +++ b/src/game/BattleGroundAA.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,7 +37,7 @@ class BattleGroundAA : public BattleGround public: BattleGroundAA(); ~BattleGroundAA(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index 00e1090d8d5..e4b0c82882d 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include "Language.h" #include "World.h" #include "Util.h" +#include "WorldPacket.h" // these variables aren't used outside of this file, so declare them only here uint32 BG_AB_HonorScoreTicks[BG_HONOR_MODE_NUM] = { @@ -52,7 +53,7 @@ BattleGroundAB::~BattleGroundAB() { } -void BattleGroundAB::Update(time_t diff) +void BattleGroundAB::Update(uint32 diff) { BattleGround::Update(diff); @@ -425,9 +426,9 @@ void BattleGroundAB::_NodeDeOccupied(uint8 node) { WorldSafeLocsEntry const *ClosestGrave = NULL; Player *plr; - for (std::vector<uint64>::iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) + for (std::vector<uint64>::const_iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) { - plr = objmgr.GetPlayer(*ghost_list.begin()); + plr = objmgr.GetPlayer(*itr); if( !plr ) continue; if( !ClosestGrave ) diff --git a/src/game/BattleGroundAB.h b/src/game/BattleGroundAB.h index 464108d63c9..0844f3b5c4f 100644 --- a/src/game/BattleGroundAB.h +++ b/src/game/BattleGroundAB.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -238,7 +238,7 @@ class BattleGroundAB : public BattleGround BattleGroundAB(); ~BattleGroundAB(); - void Update(time_t diff); + void Update(uint32 diff); void AddPlayer(Player *plr); void RemovePlayer(Player *plr,uint64 guid); void HandleAreaTrigger(Player *Source, uint32 Trigger); diff --git a/src/game/BattleGroundAV.cpp b/src/game/BattleGroundAV.cpp index c65ca479712..c8d1ed3b673 100644 --- a/src/game/BattleGroundAV.cpp +++ b/src/game/BattleGroundAV.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,7 @@ #include "Language.h" #include "SpellAuras.h" #include "Formulas.h" +#include "WorldPacket.h" BattleGroundAV::BattleGroundAV() { @@ -294,7 +295,7 @@ Creature* BattleGroundAV::AddAVCreature(uint16 cinfoid, uint16 type ) return creature; } -void BattleGroundAV::Update(time_t diff) +void BattleGroundAV::Update(uint32 diff) { BattleGround::Update(diff); if (GetStatus() == STATUS_WAIT_JOIN && GetPlayersSize()) diff --git a/src/game/BattleGroundAV.h b/src/game/BattleGroundAV.h index e80ad47d869..d4581b07d41 100644 --- a/src/game/BattleGroundAV.h +++ b/src/game/BattleGroundAV.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1500,7 +1500,7 @@ class BattleGroundAV : public BattleGround public: BattleGroundAV(); ~BattleGroundAV(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index 6f4ac89c64e..f63c6822c5b 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ #include "Creature.h" #include "ObjectMgr.h" #include "MapManager.h" +#include "WorldPacket.h" #include "Language.h" BattleGroundBE::BattleGroundBE() @@ -37,7 +38,7 @@ BattleGroundBE::~BattleGroundBE() } -void BattleGroundBE::Update(time_t diff) +void BattleGroundBE::Update(uint32 diff) { BattleGround::Update(diff); diff --git a/src/game/BattleGroundBE.h b/src/game/BattleGroundBE.h index a16464dd31b..a3826fcdd7d 100644 --- a/src/game/BattleGroundBE.h +++ b/src/game/BattleGroundBE.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,7 +57,7 @@ class BattleGroundBE : public BattleGround public: BattleGroundBE(); ~BattleGroundBE(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundDS.cpp b/src/game/BattleGroundDS.cpp new file mode 100644 index 00000000000..825a52967b6 --- /dev/null +++ b/src/game/BattleGroundDS.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundDS.h" + +BattleGroundDS::BattleGroundDS() +{ + +} + +BattleGroundDS::~BattleGroundDS() +{ + +} + +void BattleGroundDS::Update(uint32 diff) +{ + BattleGround::Update(diff); +} + +void BattleGroundDS::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundDSScore* sc = new BattleGroundDSScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundDS::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) +{ +} + +void BattleGroundDS::HandleKillPlayer(Player* player, Player* killer) +{ + BattleGround::HandleKillPlayer(player, killer); +} + +void BattleGroundDS::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) +{ +} + +bool BattleGroundDS::SetupBattleGround() +{ + return true; +} diff --git a/src/game/BattleGroundDS.h b/src/game/BattleGroundDS.h new file mode 100644 index 00000000000..7f9de8ca7de --- /dev/null +++ b/src/game/BattleGroundDS.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDDS_H +#define __BATTLEGROUNDDS_H + +class BattleGround; + +class BattleGroundDSScore : public BattleGroundScore +{ + public: + BattleGroundDSScore() {}; + virtual ~BattleGroundDSScore() {}; + //TODO fix me +}; + +class BattleGroundDS : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundDS(); + ~BattleGroundDS(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + void HandleKillPlayer(Player* player, Player *killer); +}; +#endif diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 1af6aaabf8b..baaa345d96d 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +27,8 @@ #include "ObjectMgr.h" #include "MapManager.h" #include "Language.h" -#include "World.h" +#include "World.h" //music +#include "WorldPacket.h" #include "Util.h" // these variables aren't used outside of this file, so declare them only here @@ -51,7 +52,7 @@ BattleGroundEY::~BattleGroundEY() { } -void BattleGroundEY::Update(time_t diff) +void BattleGroundEY::Update(uint32 diff) { BattleGround::Update(diff); // after bg start we get there (once) diff --git a/src/game/BattleGroundEY.h b/src/game/BattleGroundEY.h index 0152a889f30..c99c0eeb4d4 100644 --- a/src/game/BattleGroundEY.h +++ b/src/game/BattleGroundEY.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -300,7 +300,7 @@ class BattleGroundEY : public BattleGround public: BattleGroundEY(); ~BattleGroundEY(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index fc99fe3f1fe..33d8ab4fe4c 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -53,7 +53,7 @@ void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data ) // Stop the npc if moving unit->StopMoving(); - uint32 bgTypeId = objmgr.GetBattleMasterBG(unit->GetEntry()); + BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(unit->GetEntry()); if(!_player->GetBGAccessByLevel(bgTypeId)) { @@ -65,7 +65,7 @@ void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data ) SendBattlegGroundList(guid, bgTypeId); } -void WorldSession::SendBattlegGroundList( uint64 guid, uint32 bgTypeId ) +void WorldSession::SendBattlegGroundList( uint64 guid, BattleGroundTypeId bgTypeId ) { WorldPacket data; sBattleGroundMgr.BuildBattleGroundListPacket(&data, guid, _player, bgTypeId); @@ -77,26 +77,28 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) CHECK_PACKET_SIZE(recv_data, 8+4+4+1); uint64 guid; - uint32 bgTypeId; + uint32 bgTypeId_; uint32 instanceId; uint8 joinAsGroup; Group * grp; recv_data >> guid; // battlemaster guid - recv_data >> bgTypeId; // battleground type id (DBC id) + recv_data >> bgTypeId_; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group - if(bgTypeId >= MAX_BATTLEGROUND_TYPES) + if(!sBattlemasterListStore.LookupEntry(bgTypeId_)) { - sLog.outError("Battleground: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow()); + sLog.outError("Battleground: invalid bgtype (%u) received. possible cheater? player guid %u",bgTypeId_,_player->GetGUIDLow()); return; } + BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); + sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT, guid); // can do this, since it's battleground, not arena - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, 0); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, 0); // ignore if player is already in BG if(_player->InBattleGround()) @@ -180,6 +182,8 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) } sLog.outDebug("Battleground: group end"); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); + if(!ginfo->IsInvitedToBGInstanceGUID) + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } else { @@ -196,6 +200,8 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); + if(!ginfo->IsInvitedToBGInstanceGUID) + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } } @@ -270,19 +276,15 @@ void WorldSession::HandleBattleGroundListOpcode( WorldPacket &recv_data ) uint32 bgTypeId; recv_data >> bgTypeId; // id from DBC - if(bgTypeId >= MAX_BATTLEGROUND_TYPES) + BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); + if(!bl) { sLog.outError("Battleground: invalid bgtype received."); return; } - BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); - - if(!bl) - return; - WorldPacket data; - sBattleGroundMgr.BuildBattleGroundListPacket(&data, _player->GetGUID(), _player, bgTypeId); + sBattleGroundMgr.BuildBattleGroundListPacket(&data, _player->GetGUID(), _player, BattleGroundTypeId(bgTypeId)); SendPacket( &data ); } @@ -295,15 +297,15 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) uint8 type; // arenatype if arena uint8 unk2; // unk, can be 0x0 (may be if was invited?) and 0x1 uint32 instanceId; - uint32 bgTypeId; // type id from dbc + uint32 bgTypeId_; // type id from dbc uint16 unk; // 0x1F90 constant? uint8 action; // enter battle 0x1, leave queue 0x0 - recv_data >> type >> unk2 >> bgTypeId >> unk >> action; + recv_data >> type >> unk2 >> bgTypeId_ >> unk >> action; - if(bgTypeId >= MAX_BATTLEGROUND_TYPES) + if(!sBattlemasterListStore.LookupEntry(bgTypeId_)) { - sLog.outError("Battleground: invalid bgtype received."); + sLog.outError("Battleground: invalid bgtype (%u) received.",bgTypeId_); // update battleground slots for the player to fix his UI and sent data. // this is a HACK, I don't know why the client starts sending invalid packets in the first place. // it usually happens with extremely high latency (if debugging / stepping in the code for example) @@ -327,7 +329,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) BattleGround * bg = NULL; // get possibly needed data from groupinfo - bgTypeId = itrPlayerStatus->second.GroupInfo->BgTypeId; + BattleGroundTypeId bgTypeId = itrPlayerStatus->second.GroupInfo->BgTypeId; uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated; uint8 status = 0; @@ -363,10 +365,12 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) return; } + BattleGroundTypeId bgTypeId = BattleGroundTypeId(bgTypeId_); + uint32 bgQueueTypeId = 0; // get the bg what we were invited to BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus; - bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId,type); + bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId,type); itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) @@ -391,7 +395,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) if(!bg) { - sLog.outError("Battleground: bg not found."); + sLog.outError("Battleground: bg not found for type id %u.",bgTypeId); return; } @@ -460,7 +464,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) // bg->AddPlayer(_player,team); sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetInstanceID(),bg->GetTypeID(),bgQueueTypeId); break; - case 0: // leave queue + case 0: // leave queue queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); /* if player leaves rated arena match before match start, it is counted as he played but he lost @@ -527,7 +531,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) BattleGround *bg = _player->GetBattleGround(); if(bg) { - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); if((bg->GetStatus() <= STATUS_IN_PROGRESS)) { @@ -537,7 +541,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { uint32 queue_id = _player->GetBattleGroundQueueId(i); // battlegroundqueueid stores the type id, not the instance id, so this is definitely wrong - uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); + uint8 arenatype = BattleGroundMgr::BGArenaType(queue_id); uint8 isRated = 0; if (i == queueSlot || !queue_id) // we need to get the instance ids continue; @@ -549,7 +553,7 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; isRated = itrPlayerStatus->second.GroupInfo->IsRated; } - BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(sBattleGroundMgr.BGTemplateId(queue_id)); // try this + BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(BattleGroundMgr::BGTemplateId(queue_id)); // try this if(bg2) { //in this call is small bug, this call should be filled by player's waiting time in queue @@ -568,8 +572,8 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) uint32 queue_id = _player->GetBattleGroundQueueId(i); if(!queue_id) continue; - uint32 bgTypeId = sBattleGroundMgr.BGTemplateId(queue_id); - uint8 arenatype = sBattleGroundMgr.BGArenaType(queue_id); + BattleGroundTypeId bgTypeId = BattleGroundMgr::BGTemplateId(queue_id); + uint8 arenatype = BattleGroundMgr::BGArenaType(queue_id); uint8 isRated = 0; BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); @@ -696,8 +700,8 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) return; } - uint8 bgTypeId = bg->GetTypeID(); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); + BattleGroundTypeId bgTypeId = bg->GetTypeID(); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); // check queueing conditions if(!asGroup) @@ -784,6 +788,8 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) } sLog.outDebug("Battleground: arena join as group end"); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); + if(isRated) + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AnnounceWorld(ginfo, _player->GetGUID(), true); } else { diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index b4a28d93fd8..f86b6f4915a 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ */ #include "Common.h" +#include "SharedDefines.h" #include "Player.h" #include "BattleGroundMgr.h" #include "BattleGroundAV.h" @@ -29,16 +30,21 @@ #include "BattleGroundBE.h" #include "BattleGroundAA.h" #include "BattleGroundRL.h" -#include "SharedDefines.h" -#include "Policies/SingletonImp.h" +#include "BattleGroundSA.h" +#include "BattleGroundDS.h" +#include "BattleGroundRV.h" #include "MapManager.h" #include "Map.h" #include "MapInstanced.h" #include "ObjectMgr.h" #include "ProgressBar.h" -#include "World.h" #include "Chat.h" #include "ArenaTeam.h" +#include "World.h" +#include "WorldPacket.h" +#include "ProgressBar.h" + +#include "Policies/SingletonImp.h" INSTANTIATE_SINGLETON_1( BattleGroundMgr ); @@ -71,7 +77,7 @@ BattleGroundQueue::~BattleGroundQueue() } // initialize eligible groups from the given source matching the given specifications -void BattleGroundQueue::EligibleGroups::Init(BattleGroundQueue::QueuedGroupsList *source, uint32 BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType, bool IsRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) +void BattleGroundQueue::EligibleGroups::Init(BattleGroundQueue::QueuedGroupsList *source, BattleGroundTypeId BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType, bool IsRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) { // clear from prev initialization clear(); @@ -136,7 +142,7 @@ void BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo * ginfo) } // add group to bg queue with the given leader and bg specifications -GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 arenaRating, uint32 arenateamid) +GroupQueueInfo * BattleGroundQueue::AddGroup(Player *leader, BattleGroundTypeId BgTypeId, uint8 ArenaType, bool isRated, uint32 arenaRating, uint32 arenateamid) { uint32 queue_id = leader->GetBattleGroundQueueIdFromLevel(); @@ -177,7 +183,7 @@ void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) ginfo->Players[plr->GetGUID()] = &info; } -void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) +void BattleGroundQueue::RemovePlayer(const uint64& guid, bool decreaseInvitedCount) { Player *plr = objmgr.GetPlayer(guid); @@ -260,6 +266,11 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) // remove player queue info m_QueuedPlayers[queue_id].erase(itr); // remove group queue info if needed + + //if we left BG queue(not porting) OR if arena team left queue for rated match + if((decreaseInvitedCount && !group->ArenaType) || (group->ArenaType && group->IsRated && group->Players.empty())) + AnnounceWorld(group, guid, false); + if(group->Players.empty()) { m_QueuedGroups[queue_id].erase(group_itr); @@ -275,7 +286,7 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first)) { BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(group->BgTypeId,group->ArenaType); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(group->BgTypeId,group->ArenaType); uint32 queueSlot = plr2->GetBattleGroundQueueIndex(bgQueueTypeId); plr2->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs WorldPacket data; @@ -288,6 +299,85 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) } } +void BattleGroundQueue::AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue) +{ + + if(ginfo->ArenaType) //if Arena + { + if( sWorld.getConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE) && ginfo->IsRated) + { + BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId); + if(!bg) + return; + + char const* bgName = bg->GetName(); + if(isAddedToQueue) + sWorld.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, bgName, ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating); + else + sWorld.SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, bgName, ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating); + } + } + else //if BG + { + if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) + { + Player *plr = objmgr.GetPlayer(playerGUID); + if(!plr) + return; + + BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(ginfo->BgTypeId); + if(!bg) + return; + + uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(); + char const* bgName = bg->GetName(); + + uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id); + uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id); + + // replace hardcoded max level by player max level for nice output + if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); + + int8 MinPlayers = bg->GetMinPlayersPerTeam(); + + uint8 qHorde = 0; + uint8 qAlliance = 0; + + BattleGroundTypeId bgTypeId = ginfo->BgTypeId; + QueuedPlayersMap::iterator itr; + for(itr = m_QueuedPlayers[queue_id].begin(); itr!= m_QueuedPlayers[queue_id].end(); ++itr) + { + if(itr->second.GroupInfo->BgTypeId == bgTypeId) + { + switch(itr->second.GroupInfo->Team) + { + case HORDE: + qHorde++; break; + case ALLIANCE: + qAlliance++; break; + default: + break; + } + } + } + + // Show queue status to player only (when joining queue) + if(sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY)) + { + ChatHandler(plr).PSendSysMessage(LANG_BG_QUEUE_ANNOUNCE_SELF, + bgName, q_min_level, q_max_level, qAlliance, MinPlayers, qHorde, MinPlayers); + } + // System message + else + { + sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, + bgName, q_min_level, q_max_level, qAlliance, MinPlayers, qHorde, MinPlayers); + } + } + } +} + bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side) { // set side if needed @@ -299,7 +389,7 @@ bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * b // not yet invited // set invitation ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID(); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); // loop through the players for(std::map<uint64,PlayerQueueInfo*>::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr) { @@ -362,26 +452,25 @@ bool BattleGroundQueue::SelectionPool::Build(uint32 MinPlayers, uint32 MaxPlayer } // this function is responsible for the selection of queued groups when trying to create new battlegrounds -bool BattleGroundQueue::BuildSelectionPool(uint32 bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType, bool isRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) +bool BattleGroundQueue::BuildSelectionPool(BattleGroundTypeId bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType, bool isRated, uint32 MinRating, uint32 MaxRating, uint32 DisregardTime, uint32 excludeTeam) { uint32 side; switch(mode) { - case NORMAL_ALLIANCE: - case ONESIDE_ALLIANCE_TEAM1: - case ONESIDE_ALLIANCE_TEAM2: - side = ALLIANCE; - break; - case NORMAL_HORDE: - case ONESIDE_HORDE_TEAM1: - case ONESIDE_HORDE_TEAM2: - side = HORDE; - break; - default: - //unknown mode, return false - sLog.outDebug("Battleground: unknown selection pool build mode, returning..."); - return false; - break; + case NORMAL_ALLIANCE: + case ONESIDE_ALLIANCE_TEAM1: + case ONESIDE_ALLIANCE_TEAM2: + side = ALLIANCE; + break; + case NORMAL_HORDE: + case ONESIDE_HORDE_TEAM1: + case ONESIDE_HORDE_TEAM2: + side = HORDE; + break; + default: + //unknown mode, return false + sLog.outDebug("Battleground: unknown selection pool build mode, returning..."); + return false; } // initiate the groups eligible to create the bg @@ -414,7 +503,7 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) { uint32 queue_id = bg->GetQueueType(); uint32 bgInstanceId = bg->GetInstanceID(); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); QueuedGroupsList::iterator itr, next; for(itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); itr = next) { @@ -455,7 +544,7 @@ void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) RemovePlayer(itr2->first, true); // this is probably unneeded, since this player was already invited -> does not fit when initing eligible groups // but updating the queue can't hurt - Update(bgQueueTypeId, bg->GetQueueType()); + Update(bg->GetTypeID(), bg->GetQueueType()); // send info to client WorldPacket data; sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0); @@ -471,7 +560,7 @@ this method is called when group is inserted, or player / group is removed from it must be called after fully adding the members of a group to ensure group joining should be called after removeplayer functions in some cases */ -void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype, bool isRated, uint32 arenaRating) +void BattleGroundQueue::Update(BattleGroundTypeId bgTypeId, uint32 queue_id, uint8 arenatype, bool isRated, uint32 arenaRating) { if (queue_id >= MAX_BATTLEGROUND_QUEUES) { @@ -484,7 +573,7 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype if (m_QueuedGroups[queue_id].empty()) return; - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bgTypeId, arenatype); //battleground with free slot for player should be always the last in this queue BGFreeSlotQueueType::iterator itr, next; @@ -559,6 +648,14 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype } } } + // BG case + else + { + if(sBattleGroundMgr.isTesting()) + { + MinPlayersPerTeam = 1; + } + } // found out the minimum and maximum ratings the newly added team should battle against // arenaRating is the rating of the latest joined team @@ -586,14 +683,14 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype sLog.outDebug("Battleground: horde pool wasn't created"); // if selection pools are ready, create the new bg - if (bAllyOK && bHordeOK) + if ((bAllyOK && bHordeOK) || ( sBattleGroundMgr.isTesting() && (bAllyOK || bHordeOK))) { BattleGround * bg2 = 0; // special handling for arenas if(bg_template->isArena()) { // Find a random arena, that can be created - uint8 arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; + BattleGroundTypeId arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; uint32 arena_num = urand(0,2); if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) && @@ -635,6 +732,15 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype { // create new battleground bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId); + if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) + { + char const* bgName = bg2->GetName(); + uint32 q_min_level = Player::GetMinLevelForBattleGroundQueueId(queue_id); + uint32 q_max_level = Player::GetMaxLevelForBattleGroundQueueId(queue_id); + if(q_max_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + q_max_level = sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); + sWorld.SendWorldText(LANG_BG_STARTED_ANNOUNCE_WORLD, bgName, q_min_level, q_max_level); + } } if(!bg2) @@ -748,7 +854,7 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype } // create random arena - uint8 arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; + BattleGroundTypeId arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; uint32 arena_num = urand(0,2); BattleGround* bg2 = NULL; if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && @@ -850,22 +956,18 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) if (!bg) return true; - uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue { - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); - uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); - if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue + // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems + BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; + BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); + if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) { - // check if player is invited to this bg ... this check must be here, because when player leaves queue and joins another, it would cause a problems - BattleGroundQueue::QueuedPlayersMap const& qpMap = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; - BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); - if (qItr != qpMap.end() && qItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) - { - WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0); - plr->GetSession()->SendPacket(&data); - } + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, qItr->second.GroupInfo->Team, queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0); + plr->GetSession()->SendPacket(&data); } } return true; //event will be deleted @@ -890,7 +992,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) sLog.outDebug("Battleground: removing player %u from bg queue for instance %u because of not pressing enter battle in time.",plr->GetGUIDLow(),m_BgInstanceGUID); - uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 bgQueueTypeId = BattleGroundMgr::BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue { @@ -910,7 +1012,7 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) } plr->RemoveBattleGroundQueueId(bgQueueTypeId); sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true); - sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgQueueTypeId, bg->GetQueueType()); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bg->GetTypeID(),bg->GetQueueType()); WorldPacket data; sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, m_PlayersTeam, queueSlot, STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); @@ -933,34 +1035,38 @@ void BGQueueRemoveEvent::Abort(uint64 /*e_time*/) /*** BATTLEGROUND MANAGER ***/ /*********************************************************/ -BattleGroundMgr::BattleGroundMgr() +BattleGroundMgr::BattleGroundMgr() : m_AutoDistributionTimeChecker(0), m_ArenaTesting(false) { m_BattleGrounds.clear(); - m_AutoDistributePoints = (bool)sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS); - m_MaxRatingDifference = sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE); - m_RatingDiscardTimer = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); - m_PrematureFinishTimer = sWorld.getConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER); - m_NextRatingDiscardUpdate = m_RatingDiscardTimer; - m_AutoDistributionTimeChecker = 0; - m_ArenaTesting = false; + m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); + m_Testing=false; } BattleGroundMgr::~BattleGroundMgr() { - BattleGroundSet::iterator itr, next; - for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) + DeleteAlllBattleGrounds(); +} + +void BattleGroundMgr::DeleteAlllBattleGrounds() +{ + for(BattleGroundSet::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end();) { - next = itr; - ++next; BattleGround * bg = itr->second; - m_BattleGrounds.erase(itr); + m_BattleGrounds.erase(itr++); delete bg; } - m_BattleGrounds.clear(); + + // destroy template battlegrounds that listed only in queues (other already terminated) + for(uint32 bgTypeId = 0; bgTypeId < MAX_BATTLEGROUND_TYPE_ID; ++bgTypeId) + { + // ~BattleGround call unregistring BG from queue + while(!BGFreeSlotQueue[bgTypeId].empty()) + delete BGFreeSlotQueue[bgTypeId].front(); + } } // used to update running battlegrounds, and delete finished ones -void BattleGroundMgr::Update(time_t diff) +void BattleGroundMgr::Update(uint32 diff) { BattleGroundSet::iterator itr, next; for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) @@ -978,7 +1084,7 @@ void BattleGroundMgr::Update(time_t diff) } } // if rating difference counts, maybe force-update queues - if(m_MaxRatingDifference) + if(sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE)) { // it's time to force update if(m_NextRatingDiscardUpdate < diff) @@ -987,12 +1093,12 @@ void BattleGroundMgr::Update(time_t diff) m_BattleGroundQueues[BATTLEGROUND_QUEUE_2v2].Update(BATTLEGROUND_AA,6,ARENA_TYPE_2v2,true,0); m_BattleGroundQueues[BATTLEGROUND_QUEUE_3v3].Update(BATTLEGROUND_AA,6,ARENA_TYPE_3v3,true,0); m_BattleGroundQueues[BATTLEGROUND_QUEUE_5v5].Update(BATTLEGROUND_AA,6,ARENA_TYPE_5v5,true,0); - m_NextRatingDiscardUpdate = m_RatingDiscardTimer; + m_NextRatingDiscardUpdate = sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); } else m_NextRatingDiscardUpdate -= diff; } - if(m_AutoDistributePoints) + if(sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS)) { if(m_AutoDistributionTimeChecker < diff) { @@ -1054,6 +1160,15 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro case BATTLEGROUND_RL: *data << uint8(8); break; + case BATTLEGROUND_SA: + *data << uint8(9); + break; + case BATTLEGROUND_DS: + *data << uint8(10); + break; + case BATTLEGROUND_RV: + *data << uint8(11); + break; default: // unknown *data << uint8(0); break; @@ -1098,17 +1213,18 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) { uint8 type = (bg->isArena() ? 1 : 0); - // last check on 2.4.1 + // last check on 3.0.3 data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize())); - *data << uint8(type); // seems to be type (battleground=0/arena=1) + *data << uint8(type); // type (battleground=0/arena=1) if(type) // arena { // it seems this must be according to BG_WINNER_A/H and _NOT_ BG_TEAM_A/H for(int i = 1; i >= 0; --i) { - *data << uint32(3000-bg->m_ArenaTeamRatingChanges[i]); // rating change: showed value - 3000 + *data << uint32(bg->m_ArenaTeamRatingChanges[i]); *data << uint32(3999); // huge thanks for TOM_RUS for this! + *data << uint32(0); // unknown - new in 3.0.3 sLog.outDebug("rating change: %d", bg->m_ArenaTeamRatingChanges[i]); } for(int i = 1; i >= 0; --i) @@ -1122,9 +1238,9 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) } } - if(bg->GetWinner() == 2) + if(bg->GetStatus() != STATUS_WAIT_LEAVE) { - *data << uint8(0); // bg in progress + *data << uint8(0); // bg not ended } else { @@ -1138,9 +1254,6 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) { *data << (uint64)itr->first; *data << (int32)itr->second->KillingBlows; - Player *plr = objmgr.GetPlayer(itr->first); - uint32 team = bg->GetPlayerTeam(itr->first); - if(!team && plr) team = plr->GetTeam(); if(type == 0) { *data << (int32)itr->second->HonorableKills; @@ -1149,18 +1262,12 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) } else { - // that part probably wrong - if(plr) - { - if(team == HORDE) - *data << uint8(0); - else if(team == ALLIANCE) - { - *data << uint8(1); - } - else - *data << uint8(0); - } + Player *plr = objmgr.GetPlayer(itr->first); + uint32 team = bg->GetPlayerTeam(itr->first); + if(!team && plr) + team = plr->GetTeam(); + if( ( bg->GetWinner()==0 && team == ALLIANCE ) || ( bg->GetWinner()==1 && team==HORDE ) ) + *data << uint8(1); else *data << uint8(0); } @@ -1187,13 +1294,16 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) *data << (uint32)((BattleGroundABScore*)itr->second)->BasesDefended; // bases defended break; case BATTLEGROUND_EY: - *data << (uint32)0x00000001; // count of next fields + *data << (uint32)0x00000001; // count of next fields *data << (uint32)((BattleGroundEYScore*)itr->second)->FlagCaptures; // flag captures break; case BATTLEGROUND_NA: case BATTLEGROUND_BE: case BATTLEGROUND_AA: case BATTLEGROUND_RL: + case BATTLEGROUND_SA: // wotlk + case BATTLEGROUND_DS: // wotlk + case BATTLEGROUND_RV: // wotlk *data << (int32)0; // 0 break; default: @@ -1204,7 +1314,7 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) } } -void BattleGroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 bgTypeId) +void BattleGroundMgr::BuildGroupJoinedBattlegroundPacket(WorldPacket *data, BattleGroundTypeId bgTypeId) { /*bgTypeId is: 0 - Your group has joined a battleground queue, but you are not eligible @@ -1281,25 +1391,24 @@ void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 te plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME)); } -BattleGround * BattleGroundMgr::GetBattleGroundTemplate(uint32 bgTypeId) +BattleGround * BattleGroundMgr::GetBattleGroundTemplate(BattleGroundTypeId bgTypeId) { return BGFreeSlotQueue[bgTypeId].empty() ? NULL : BGFreeSlotQueue[bgTypeId].back(); } // create a new battleground that will really be used to play -BattleGround * BattleGroundMgr::CreateNewBattleGround(uint32 bgTypeId) +BattleGround * BattleGroundMgr::CreateNewBattleGround(BattleGroundTypeId bgTypeId) { - BattleGround *bg = NULL; - // get the template BG BattleGround *bg_template = GetBattleGroundTemplate(bgTypeId); - if(!bg_template) { sLog.outError("BattleGround: CreateNewBattleGround - bg template not found for %u", bgTypeId); - return 0; + return NULL; } + BattleGround *bg = NULL; + // create a copy of the BG template switch(bgTypeId) { @@ -1327,6 +1436,15 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(uint32 bgTypeId) case BATTLEGROUND_RL: bg = new BattleGroundRL(*(BattleGroundRL*)bg_template); break; + case BATTLEGROUND_SA: + bg = new BattleGroundSA(*(BattleGroundSA*)bg_template); + break; + case BATTLEGROUND_DS: + bg = new BattleGroundDS(*(BattleGroundDS*)bg_template); + break; + case BATTLEGROUND_RV: + bg = new BattleGroundRV(*(BattleGroundRV*)bg_template); + break; default: //bg = new BattleGround; return 0; @@ -1358,7 +1476,7 @@ BattleGround * BattleGroundMgr::CreateNewBattleGround(uint32 bgTypeId) } // used to create the BG templates -uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO) +uint32 BattleGroundMgr::CreateBattleGround(BattleGroundTypeId bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO) { // Create the BG BattleGround *bg = NULL; @@ -1373,6 +1491,9 @@ uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPer case BATTLEGROUND_AA: bg = new BattleGroundAA; break; case BATTLEGROUND_EY: bg = new BattleGroundEY; break; case BATTLEGROUND_RL: bg = new BattleGroundRL; break; + case BATTLEGROUND_SA: bg = new BattleGroundSA; break; + case BATTLEGROUND_DS: bg = new BattleGroundDS; break; + case BATTLEGROUND_RV: bg = new BattleGroundRV; break; default:bg = new BattleGround; break; // placeholder for non implemented BG } @@ -1438,16 +1559,18 @@ void BattleGroundMgr::CreateInitialBattleGrounds() Field *fields = result->Fetch(); bar.step(); - uint32 bgTypeID = fields[0].GetUInt32(); + uint32 bgTypeID_ = fields[0].GetUInt32(); - // can be overwrited by values from DB - bl = sBattlemasterListStore.LookupEntry(bgTypeID); + // can be overwrite by values from DB + bl = sBattlemasterListStore.LookupEntry(bgTypeID_); if(!bl) { - sLog.outError("Battleground ID %u not found in BattlemasterList.dbc. Battleground not created.",bgTypeID); + sLog.outError("Battleground ID %u not found in BattlemasterList.dbc. Battleground not created.",bgTypeID_); continue; } + BattleGroundTypeId bgTypeID = BattleGroundTypeId(bgTypeID_); + MaxPlayersPerTeam = bl->maxplayersperteam; MinPlayersPerTeam = bl->maxplayersperteam/2; MinLvl = bl->minlvl; @@ -1526,7 +1649,7 @@ void BattleGroundMgr::CreateInitialBattleGrounds() void BattleGroundMgr::InitAutomaticArenaPointDistribution() { - if(m_AutoDistributePoints) + if(sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS)) { sLog.outDebug("Initializing Automatic Arena Point Distribution"); QueryResult * result = CharacterDatabase.Query("SELECT NextArenaPointDistributionTime FROM saved_variables"); @@ -1548,9 +1671,9 @@ void BattleGroundMgr::InitAutomaticArenaPointDistribution() void BattleGroundMgr::DistributeArenaPoints() { // used to distribute arena points based on last week's stats - sWorld.SendGlobalText("Flushing Arena points based on team ratings, this may take a few minutes. Please stand by...", NULL); + sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_START); - sWorld.SendGlobalText("Distributing arena points to players...", NULL); + sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_START); //temporary structure for storing maximum points to add values for all players std::map<uint32, uint32> PlayerPoints; @@ -1577,9 +1700,9 @@ void BattleGroundMgr::DistributeArenaPoints() PlayerPoints.clear(); - sWorld.SendGlobalText("Finished setting arena points for online players.", NULL); + sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_ONLINE_END); - sWorld.SendGlobalText("Modifying played count, arena points etc. for loaded arena teams, sending updated stats to online players...", NULL); + sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_START); for(ObjectMgr::ArenaTeamMap::iterator titr = objmgr.GetArenaTeamMapBegin(); titr != objmgr.GetArenaTeamMapEnd(); ++titr) { if(ArenaTeam * at = titr->second) @@ -1590,12 +1713,12 @@ void BattleGroundMgr::DistributeArenaPoints() } } - sWorld.SendGlobalText("Modification done.", NULL); + sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_TEAM_END); - sWorld.SendGlobalText("Done flushing Arena points.", NULL); + sWorld.SendWorldText(LANG_DIST_ARENA_POINTS_END); } -void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player* plr, uint32 bgTypeId) +void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, const uint64& guid, Player* plr, BattleGroundTypeId bgTypeId) { uint32 PlayerLevel = 10; @@ -1651,7 +1774,7 @@ void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId) } } -void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid) +void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid) { WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12); uint32 time_ = 30000 - bg->GetLastResurrectTime(); // resurrect every 30 seconds @@ -1661,14 +1784,7 @@ void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround * pl->GetSession()->SendPacket(&data); } -void BattleGroundMgr::RemoveBattleGround(uint32 instanceID) -{ - BattleGroundSet::iterator itr = m_BattleGrounds.find(instanceID); - if(itr!=m_BattleGrounds.end()) - m_BattleGrounds.erase(itr); -} - -bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const +bool BattleGroundMgr::IsArenaType(BattleGroundTypeId bgTypeId) { return ( bgTypeId == BATTLEGROUND_AA || bgTypeId == BATTLEGROUND_BE || @@ -1676,95 +1792,165 @@ bool BattleGroundMgr::IsArenaType(uint32 bgTypeId) const bgTypeId == BATTLEGROUND_RL ); } -bool BattleGroundMgr::IsBattleGroundType(uint32 bgTypeId) const -{ - return !IsArenaType(bgTypeId); -} - -uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const +uint32 BattleGroundMgr::BGQueueTypeId(BattleGroundTypeId bgTypeId, uint8 arenaType) { switch(bgTypeId) { - case BATTLEGROUND_WS: - return BATTLEGROUND_QUEUE_WS; - case BATTLEGROUND_AB: - return BATTLEGROUND_QUEUE_AB; - case BATTLEGROUND_AV: - return BATTLEGROUND_QUEUE_AV; - case BATTLEGROUND_EY: - return BATTLEGROUND_QUEUE_EY; - case BATTLEGROUND_AA: - case BATTLEGROUND_NA: - case BATTLEGROUND_RL: - case BATTLEGROUND_BE: - switch(arenaType) - { - case ARENA_TYPE_2v2: - return BATTLEGROUND_QUEUE_2v2; - case ARENA_TYPE_3v3: - return BATTLEGROUND_QUEUE_3v3; - case ARENA_TYPE_5v5: - return BATTLEGROUND_QUEUE_5v5; + case BATTLEGROUND_WS: + return BATTLEGROUND_QUEUE_WS; + case BATTLEGROUND_AB: + return BATTLEGROUND_QUEUE_AB; + case BATTLEGROUND_AV: + return BATTLEGROUND_QUEUE_AV; + case BATTLEGROUND_EY: + return BATTLEGROUND_QUEUE_EY; + case BATTLEGROUND_SA: + return BATTLEGROUND_QUEUE_SA; + case BATTLEGROUND_AA: + case BATTLEGROUND_NA: + case BATTLEGROUND_RL: + case BATTLEGROUND_BE: + case BATTLEGROUND_DS: + case BATTLEGROUND_RV: + switch(arenaType) + { + case ARENA_TYPE_2v2: + return BATTLEGROUND_QUEUE_2v2; + case ARENA_TYPE_3v3: + return BATTLEGROUND_QUEUE_3v3; + case ARENA_TYPE_5v5: + return BATTLEGROUND_QUEUE_5v5; + default: + return 0; + } default: return 0; - } - default: - return 0; } } -uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId) const +BattleGroundTypeId BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId) { switch(bgQueueTypeId) { - case BATTLEGROUND_QUEUE_WS: - return BATTLEGROUND_WS; - case BATTLEGROUND_QUEUE_AB: - return BATTLEGROUND_AB; - case BATTLEGROUND_QUEUE_AV: - return BATTLEGROUND_AV; - case BATTLEGROUND_QUEUE_EY: - return BATTLEGROUND_EY; - case BATTLEGROUND_QUEUE_2v2: - case BATTLEGROUND_QUEUE_3v3: - case BATTLEGROUND_QUEUE_5v5: - return BATTLEGROUND_AA; - default: - return 0; + case BATTLEGROUND_QUEUE_WS: + return BATTLEGROUND_WS; + case BATTLEGROUND_QUEUE_AB: + return BATTLEGROUND_AB; + case BATTLEGROUND_QUEUE_AV: + return BATTLEGROUND_AV; + case BATTLEGROUND_QUEUE_EY: + return BATTLEGROUND_EY; + case BATTLEGROUND_QUEUE_SA: + return BATTLEGROUND_SA; + case BATTLEGROUND_QUEUE_2v2: + case BATTLEGROUND_QUEUE_3v3: + case BATTLEGROUND_QUEUE_5v5: + return BATTLEGROUND_AA; + default: + return BattleGroundTypeId(0); // used for unknown template (it existed and do nothing) } } -uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId) const +uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId) { switch(bgQueueTypeId) { - case BATTLEGROUND_QUEUE_2v2: - return ARENA_TYPE_2v2; - case BATTLEGROUND_QUEUE_3v3: - return ARENA_TYPE_3v3; - case BATTLEGROUND_QUEUE_5v5: - return ARENA_TYPE_5v5; - default: - return 0; + case BATTLEGROUND_QUEUE_2v2: + return ARENA_TYPE_2v2; + case BATTLEGROUND_QUEUE_3v3: + return ARENA_TYPE_3v3; + case BATTLEGROUND_QUEUE_5v5: + return ARENA_TYPE_5v5; + default: + return 0; } } +void BattleGroundMgr::ToggleTesting() +{ + m_Testing = !m_Testing; + if(m_Testing) + sWorld.SendWorldText(LANG_DEBUG_BG_ON); + else + sWorld.SendWorldText(LANG_DEBUG_BG_OFF); +} + void BattleGroundMgr::ToggleArenaTesting() { m_ArenaTesting = !m_ArenaTesting; if(m_ArenaTesting) - sWorld.SendGlobalText("Arenas are set to 1v1 for debugging. So, don't join as group.", NULL); + sWorld.SendWorldText(LANG_DEBUG_ARENA_ON); else - sWorld.SendGlobalText("Arenas are set to normal playercount.", NULL); + sWorld.SendWorldText(LANG_DEBUG_ARENA_OFF); } void BattleGroundMgr::SetHolidayWeekends(uint32 mask) { - for(uint32 bgtype = 1; bgtype <= 8; ++bgtype) + for(uint32 bgtype = 1; bgtype < MAX_BATTLEGROUND_TYPE_ID; ++bgtype) { - if(BattleGround * bg = GetBattleGroundTemplate(bgtype)) + if(BattleGround * bg = GetBattleGroundTemplate(BattleGroundTypeId(bgtype))) { bg->SetHoliday(mask & (1 << bgtype)); } } } + +uint32 BattleGroundMgr::GetMaxRatingDifference() const +{ + return sWorld.getConfig(CONFIG_ARENA_MAX_RATING_DIFFERENCE); +} + +uint32 BattleGroundMgr::GetRatingDiscardTimer() const +{ + return sWorld.getConfig(CONFIG_ARENA_RATING_DISCARD_TIMER); +} + +uint32 BattleGroundMgr::GetPrematureFinishTime() const +{ + return sWorld.getConfig(CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER); +} + +void BattleGroundMgr::LoadBattleMastersEntry() +{ + mBattleMastersMap.clear(); // need for reload case + + QueryResult *result = WorldDatabase.Query( "SELECT entry,bg_template FROM battlemaster_entry" ); + + uint32 count = 0; + + if( !result ) + { + barGoLink bar( 1 ); + bar.step(); + + sLog.outString(); + sLog.outString( ">> Loaded 0 battlemaster entries - table is empty!" ); + return; + } + + barGoLink bar( result->GetRowCount() ); + + do + { + ++count; + bar.step(); + + Field *fields = result->Fetch(); + + uint32 entry = fields[0].GetUInt32(); + uint32 bgTypeId = fields[1].GetUInt32(); + if (!sBattlemasterListStore.LookupEntry(bgTypeId)) + { + sLog.outErrorDb("Table `battlemaster_entry` contain entry %u for not existed battleground type %u, ignored.",entry,bgTypeId); + continue; + } + + mBattleMastersMap[entry] = BattleGroundTypeId(bgTypeId); + + } while( result->NextRow() ); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u battlemaster entries", count ); +} diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 70b899d5f85..2b684487e1e 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,10 +21,8 @@ #ifndef __BATTLEGROUNDMGR_H #define __BATTLEGROUNDMGR_H +#include "Common.h" #include "BattleGround.h" -#include "Policies/Singleton.h" - -class BattleGround; //TODO it is not possible to have this structure, because we should have BattlegroundSet for each queue //so i propose to change this type to array 1..MAX_BATTLEGROUND_TYPES of sets or maps.. @@ -32,13 +30,13 @@ typedef std::map<uint32, BattleGround*> BattleGroundSet; //typedef std::map<uint32, BattleGroundQueue*> BattleGroundQueueSet; typedef std::deque<BattleGround*> BGFreeSlotQueueType; -#define MAX_BATTLEGROUND_QUEUES 7 // for level ranges 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70+ +typedef UNORDERED_MAP<uint32, BattleGroundTypeId> BattleMastersMap; -#define MAX_BATTLEGROUND_TYPES 9 // each BG type will be in array +#define MAX_BATTLEGROUND_QUEUES 8 // for level ranges 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70-79, 80+ -#define MAX_BATTLEGROUND_QUEUE_TYPES 8 +#define MAX_BATTLEGROUND_QUEUE_TYPES 9 -#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day +#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day struct GroupQueueInfo; // type predefinition struct PlayerQueueInfo // stores information for players in queue @@ -53,7 +51,7 @@ struct GroupQueueInfo // stores informatio { std::map<uint64, PlayerQueueInfo*> Players; // player queue info map uint32 Team; // Player team (ALLIANCE/HORDE) - uint32 BgTypeId; // battleground type id + BattleGroundTypeId BgTypeId; // battleground type id bool IsRated; // rated uint8 ArenaType; // 2v2, 3v3, 5v5 or 0 when BG uint32 ArenaTeamId; // team id if rated match @@ -70,13 +68,14 @@ class BattleGroundQueue BattleGroundQueue(); ~BattleGroundQueue(); - void Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype = 0, bool isRated = false, uint32 minRating = 0); + void Update(BattleGroundTypeId bgTypeId, uint32 queue_id, uint8 arenatype = 0, bool isRated = false, uint32 minRating = 0); - GroupQueueInfo * AddGroup(Player * leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0); + GroupQueueInfo * AddGroup(Player * leader, BattleGroundTypeId bgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0); void AddPlayer(Player *plr, GroupQueueInfo *ginfo); - void RemovePlayer(uint64 guid, bool decreaseInvitedCount); + void RemovePlayer(const uint64& guid, bool decreaseInvitedCount); void DecreaseGroupLength(uint32 queueId, uint32 AsGroup); void BGEndedRemoveInvites(BattleGround * bg); + void AnnounceWorld(GroupQueueInfo *ginfo, const uint64& playerGUID, bool isAddedToQueue); typedef std::map<uint64, PlayerQueueInfo> QueuedPlayersMap; QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES]; @@ -88,7 +87,7 @@ class BattleGroundQueue class EligibleGroups : public std::list<GroupQueueInfo *> { public: - void Init(QueuedGroupsList * source, uint32 BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType = 0, bool IsRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); + void Init(QueuedGroupsList * source, BattleGroundTypeId BgTypeId, uint32 side, uint32 MaxPlayers, uint8 ArenaType = 0, bool IsRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); }; EligibleGroups m_EligibleGroups; @@ -123,7 +122,7 @@ class BattleGroundQueue SelectionPool m_SelectionPools[NUM_SELECTION_POOL_TYPES]; - bool BuildSelectionPool(uint32 bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType = 0, bool isRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); + bool BuildSelectionPool(BattleGroundTypeId bgTypeId, uint32 queue_id, uint32 MinPlayers, uint32 MaxPlayers, SelectionPoolBuildMode mode, uint8 ArenaType = 0, bool isRated = false, uint32 MinRating = 0, uint32 MaxRating = 0, uint32 DisregardTime = 0, uint32 excludeTeam = 0); private: @@ -137,7 +136,7 @@ class BattleGroundQueue class BGQueueInviteEvent : public BasicEvent { public: - BGQueueInviteEvent(uint64 pl_guid, uint32 BgInstanceGUID) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID) {}; + BGQueueInviteEvent(const uint64& pl_guid, uint32 BgInstanceGUID) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(BgInstanceGUID) {}; virtual ~BGQueueInviteEvent() {}; virtual bool Execute(uint64 e_time, uint32 p_time); @@ -153,7 +152,10 @@ class BGQueueInviteEvent : public BasicEvent class BGQueueRemoveEvent : public BasicEvent { public: - BGQueueRemoveEvent(uint64 pl_guid, uint32 bgInstanceGUID, uint32 playersTeam) : m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_PlayersTeam(playersTeam) {}; + BGQueueRemoveEvent(const uint64& pl_guid, uint32 bgInstanceGUID, uint32 playersTeam) : + m_PlayerGuid(pl_guid), m_BgInstanceGUID(bgInstanceGUID), m_PlayersTeam(playersTeam) + { + }; virtual ~BGQueueRemoveEvent() {}; virtual bool Execute(uint64 e_time, uint32 p_time); @@ -170,83 +172,89 @@ class BattleGroundMgr /* Construction */ BattleGroundMgr(); ~BattleGroundMgr(); - void Update(time_t diff); + void Update(uint32 diff); /* Packet Building */ void BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Player *plr); void BuildPlayerLeftBattleGroundPacket(WorldPacket *data, Player *plr); - void BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player *plr, uint32 bgTypeId); - void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 bgTypeId); + void BuildBattleGroundListPacket(WorldPacket *data, const uint64& guid, Player *plr, BattleGroundTypeId bgTypeId); + void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, BattleGroundTypeId bgTypeId); void BuildUpdateWorldStatePacket(WorldPacket *data, uint32 field, uint32 value); void BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg); void BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype = 0, uint8 israted = 0); void BuildPlaySoundPacket(WorldPacket *data, uint32 soundid); + void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, const uint64& guid); /* Player invitation */ // called from Queue update, or from Addplayer to queue void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team); /* Battlegrounds */ BattleGroundSet::iterator GetBattleGroundsBegin() { return m_BattleGrounds.begin(); }; - BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); }; + BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); }; - BattleGround* GetBattleGround(uint32 ID) + BattleGround* GetBattleGround(uint32 InstanceID) { - BattleGroundSet::iterator i = m_BattleGrounds.find(ID); - if(i != m_BattleGrounds.end()) - return i->second; - else - return NULL; + BattleGroundSet::iterator i = m_BattleGrounds.find(InstanceID); + return ( (i != m_BattleGrounds.end()) ? i->second : NULL ); }; - BattleGround * GetBattleGroundTemplate(uint32 bgTypeId); - BattleGround * CreateNewBattleGround(uint32 bgTypeId); + BattleGround * GetBattleGroundTemplate(BattleGroundTypeId bgTypeId); + BattleGround * CreateNewBattleGround(BattleGroundTypeId bgTypeId); - uint32 CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO); + uint32 CreateBattleGround(BattleGroundTypeId bgTypeId, uint32 MinPlayersPerTeam, uint32 MaxPlayersPerTeam, uint32 LevelMin, uint32 LevelMax, char* BattleGroundName, uint32 MapID, float Team1StartLocX, float Team1StartLocY, float Team1StartLocZ, float Team1StartLocO, float Team2StartLocX, float Team2StartLocY, float Team2StartLocZ, float Team2StartLocO); - inline void AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; }; - void RemoveBattleGround(uint32 instanceID); + void AddBattleGround(uint32 InstanceID, BattleGround* BG) { m_BattleGrounds[InstanceID] = BG; }; + void RemoveBattleGround(uint32 instanceID) { m_BattleGrounds.erase(instanceID); } void CreateInitialBattleGrounds(); + void DeleteAlllBattleGrounds(); - void SendToBattleGround(Player *pl, uint32 bgTypeId); + void SendToBattleGround(Player *pl, uint32 InstanceID); /* Battleground queues */ //these queues are instantiated when creating BattlegroundMrg BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_QUEUE_TYPES]; // public, because we need to access them in BG handler code - BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPES]; - - void SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid); + BGFreeSlotQueueType BGFreeSlotQueue[MAX_BATTLEGROUND_TYPE_ID]; - bool IsArenaType(uint32 bgTypeId) const; - bool IsBattleGroundType(uint32 bgTypeId) const; - uint32 BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const; - uint32 BGTemplateId(uint32 bgQueueTypeId) const; - uint8 BGArenaType(uint32 bgQueueTypeId) const; - - uint32 GetMaxRatingDifference() const {return m_MaxRatingDifference;} - uint32 GetRatingDiscardTimer() const {return m_RatingDiscardTimer;} + uint32 GetMaxRatingDifference() const; + uint32 GetRatingDiscardTimer() const; + uint32 GetPrematureFinishTime() const; void InitAutomaticArenaPointDistribution(); void DistributeArenaPoints(); - uint32 GetPrematureFinishTime() const {return m_PrematureFinishTimer;} void ToggleArenaTesting(); - const bool isArenaTesting() const { return m_ArenaTesting; } + void ToggleTesting(); void SetHolidayWeekends(uint32 mask); + void LoadBattleMastersEntry(); + BattleGroundTypeId GetBattleMasterBG(uint32 entry) const + { + BattleMastersMap::const_iterator itr = mBattleMastersMap.find(entry); + if(itr != mBattleMastersMap.end()) + return itr->second; + return BATTLEGROUND_WS; + } + + bool isArenaTesting() const { return m_ArenaTesting; } + bool isTesting() const { return m_Testing; } + + static bool IsArenaType(BattleGroundTypeId bgTypeId); + static bool IsBattleGroundType(BattleGroundTypeId bgTypeId) { return !BattleGroundMgr::IsArenaType(bgTypeId); } + static uint32 BGQueueTypeId(BattleGroundTypeId bgTypeId, uint8 arenaType); + static BattleGroundTypeId BGTemplateId(uint32 bgQueueTypeId); + static uint8 BGArenaType(uint32 bgQueueTypeId); private: + BattleMastersMap mBattleMastersMap; /* Battlegrounds */ BattleGroundSet m_BattleGrounds; - uint32 m_MaxRatingDifference; - uint32 m_RatingDiscardTimer; uint32 m_NextRatingDiscardUpdate; - bool m_AutoDistributePoints; uint64 m_NextAutoDistributionTime; uint32 m_AutoDistributionTimeChecker; - uint32 m_PrematureFinishTimer; bool m_ArenaTesting; + bool m_Testing; }; #define sBattleGroundMgr Trinity::Singleton<BattleGroundMgr>::Instance() diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp index f06910af986..ad6d622e71a 100644 --- a/src/game/BattleGroundNA.cpp +++ b/src/game/BattleGroundNA.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ #include "Creature.h" #include "ObjectMgr.h" #include "MapManager.h" +#include "WorldPacket.h" #include "Language.h" BattleGroundNA::BattleGroundNA() @@ -37,7 +38,7 @@ BattleGroundNA::~BattleGroundNA() } -void BattleGroundNA::Update(time_t diff) +void BattleGroundNA::Update(uint32 diff) { BattleGround::Update(diff); diff --git a/src/game/BattleGroundNA.h b/src/game/BattleGroundNA.h index 45dc9efec31..9fb94263e9c 100644 --- a/src/game/BattleGroundNA.h +++ b/src/game/BattleGroundNA.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,7 +58,7 @@ class BattleGroundNA : public BattleGround public: BattleGroundNA(); ~BattleGroundNA(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index 193578e88b0..85117acd2f6 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #include "ObjectMgr.h" #include "MapManager.h" #include "Language.h" +#include "WorldPacket.h" BattleGroundRL::BattleGroundRL() { @@ -37,7 +38,7 @@ BattleGroundRL::~BattleGroundRL() } -void BattleGroundRL::Update(time_t diff) +void BattleGroundRL::Update(uint32 diff) { BattleGround::Update(diff); diff --git a/src/game/BattleGroundRL.h b/src/game/BattleGroundRL.h index d3f58264833..0fd1af89506 100644 --- a/src/game/BattleGroundRL.h +++ b/src/game/BattleGroundRL.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,7 +54,7 @@ class BattleGroundRL : public BattleGround public: BattleGroundRL(); ~BattleGroundRL(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/BattleGroundRV.cpp b/src/game/BattleGroundRV.cpp new file mode 100644 index 00000000000..a66f0ce30e2 --- /dev/null +++ b/src/game/BattleGroundRV.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Player.h" +#include "BattleGround.h" +#include "BattleGroundRV.h" + +BattleGroundRV::BattleGroundRV() +{ + +} + +BattleGroundRV::~BattleGroundRV() +{ + +} + +void BattleGroundRV::Update(uint32 diff) +{ + BattleGround::Update(diff); +} + +void BattleGroundRV::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundRVScore* sc = new BattleGroundRVScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundRV::RemovePlayer(Player * /*plr*/, uint64 /*guid*/) +{ +} + +void BattleGroundRV::HandleKillPlayer(Player* player, Player* killer) +{ + BattleGround::HandleKillPlayer(player, killer); +} + +void BattleGroundRV::HandleAreaTrigger(Player * /*Source*/, uint32 /*Trigger*/) +{ +} + +bool BattleGroundRV::SetupBattleGround() +{ + return true; +} diff --git a/src/game/BattleGroundRV.h b/src/game/BattleGroundRV.h new file mode 100644 index 00000000000..2d2ad12c941 --- /dev/null +++ b/src/game/BattleGroundRV.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __BATTLEGROUNDRV_H +#define __BATTLEGROUNDRV_H + +class BattleGround; + +class BattleGroundRVScore : public BattleGroundScore +{ + public: + BattleGroundRVScore() {}; + virtual ~BattleGroundRVScore() {}; + //TODO fix me +}; + +class BattleGroundRV : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundRV(); + ~BattleGroundRV(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + void RemovePlayer(Player *plr, uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + bool SetupBattleGround(); + void HandleKillPlayer(Player* player, Player *killer); +}; +#endif diff --git a/src/game/BattleGroundSA.cpp b/src/game/BattleGroundSA.cpp new file mode 100644 index 00000000000..d5585fd93e9 --- /dev/null +++ b/src/game/BattleGroundSA.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BattleGround.h" +#include "BattleGroundSA.h" +#include "Player.h" + +BattleGroundSA::BattleGroundSA() +{ + +} + +BattleGroundSA::~BattleGroundSA() +{ + +} + +void BattleGroundSA::Update(uint32 diff) +{ + BattleGround::Update(diff); +} + +void BattleGroundSA::AddPlayer(Player *plr) +{ + BattleGround::AddPlayer(plr); + //create score and add it to map, default values are set in constructor + BattleGroundSAScore* sc = new BattleGroundSAScore; + + m_PlayerScores[plr->GetGUID()] = sc; +} + +void BattleGroundSA::RemovePlayer(Player* /*plr*/,uint64 /*guid*/) +{ + +} + +void BattleGroundSA::HandleAreaTrigger(Player *Source, uint32 Trigger) +{ + // this is wrong way to implement these things. On official it done by gameobject spell cast. + if(GetStatus() != STATUS_IN_PROGRESS) + return; +} + +void BattleGroundSA::UpdatePlayerScore(Player* Source, uint32 type, uint32 value) +{ + + std::map<uint64, BattleGroundScore*>::iterator itr = m_PlayerScores.find(Source->GetGUID()); + + if(itr == m_PlayerScores.end()) // player not found... + return; + + BattleGround::UpdatePlayerScore(Source,type,value); +} diff --git a/src/game/BattleGroundSA.h b/src/game/BattleGroundSA.h new file mode 100644 index 00000000000..331a41455fd --- /dev/null +++ b/src/game/BattleGroundSA.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __BATTLEGROUNDSA_H +#define __BATTLEGROUNDSA_H + +class BattleGround; + +class BattleGroundSAScore : public BattleGroundScore +{ + public: + BattleGroundSAScore() {}; + virtual ~BattleGroundSAScore() {}; +}; + +class BattleGroundSA : public BattleGround +{ + friend class BattleGroundMgr; + + public: + BattleGroundSA(); + ~BattleGroundSA(); + void Update(uint32 diff); + + /* inherited from BattlegroundClass */ + virtual void AddPlayer(Player *plr); + + void RemovePlayer(Player *plr,uint64 guid); + void HandleAreaTrigger(Player *Source, uint32 Trigger); + //bool SetupBattleGround(); + + /* Scorekeeping */ + void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); + + private: +}; +#endif diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index 755089473e8..3175f2873f9 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,8 @@ #include "GameObject.h" #include "Chat.h" #include "MapManager.h" +#include "ObjectMgr.h" +#include "WorldPacket.h" #include "Language.h" #include "World.h" @@ -58,7 +60,7 @@ BattleGroundWS::~BattleGroundWS() { } -void BattleGroundWS::Update(time_t diff) +void BattleGroundWS::Update(uint32 diff) { BattleGround::Update(diff); diff --git a/src/game/BattleGroundWS.h b/src/game/BattleGroundWS.h index 17b59d98343..0c9baee1c76 100644 --- a/src/game/BattleGroundWS.h +++ b/src/game/BattleGroundWS.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -136,7 +136,7 @@ class BattleGroundWS : public BattleGround /* Construction */ BattleGroundWS(); ~BattleGroundWS(); - void Update(time_t diff); + void Update(uint32 diff); /* inherited from BattlegroundClass */ virtual void AddPlayer(Player *plr); diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt index bcd85792b04..4d438f31d52 100644 --- a/src/game/CMakeLists.txt +++ b/src/game/CMakeLists.txt @@ -4,6 +4,8 @@ SET(game_STAT_SRCS AccountMgr.cpp AccountMgr.h + AchievementMgr.h + AchievementMgr.cpp AddonHandler.cpp AddonHandler.h AggressorAI.cpp @@ -23,22 +25,31 @@ SET(game_STAT_SRCS BattleGroundAB.cpp BattleGroundAV.cpp BattleGroundBE.cpp + BattleGroundDS.cpp BattleGroundEY.cpp BattleGroundNA.cpp BattleGroundRL.cpp + BattleGroundRV.cpp + BattleGroundSA.cpp BattleGroundWS.cpp BattleGround.h BattleGroundAA.h BattleGroundAB.h BattleGroundAV.h BattleGroundBE.h + BattleGroundDS.h BattleGroundEY.h BattleGroundNA.h BattleGroundRL.h + BattleGroundRV.h + BattleGroundSA.h BattleGroundWS.h BattleGroundHandler.cpp BattleGroundMgr.cpp BattleGroundMgr.h + Calendar.cpp + Calendar.h + CalendarHandler.cpp Cell.h CellImpl.h Channel.cpp @@ -130,6 +141,8 @@ SET(game_STAT_SRCS MapInstanced.h MapManager.cpp MapManager.h + MapReference.h + MapRefManager.h MiscHandler.cpp MotionMaster.cpp MotionMaster.h @@ -150,6 +163,8 @@ SET(game_STAT_SRCS Object.h ObjectMgr.cpp ObjectMgr.h + ObjectPosSelector.cpp + ObjectPosSelector.h Opcodes.cpp Opcodes.h OutdoorPvP.cpp @@ -240,6 +255,8 @@ SET(game_STAT_SRCS UpdateData.h UpdateFields.h UpdateMask.h + Vehicle.cpp + Vehicle.h VoiceChatHandler.cpp WaypointManager.cpp WaypointManager.h diff --git a/src/game/Calendar.cpp b/src/game/Calendar.cpp new file mode 100644 index 00000000000..0c1efb20f87 --- /dev/null +++ b/src/game/Calendar.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ diff --git a/src/game/Calendar.h b/src/game/Calendar.h new file mode 100644 index 00000000000..7a86afa7db7 --- /dev/null +++ b/src/game/Calendar.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOS_CALENDAR_H +#define MANGOS_CALENDAR_H + +class Calendar +{ + +}; +#endif diff --git a/src/game/CalendarHandler.cpp b/src/game/CalendarHandler.cpp new file mode 100644 index 00000000000..e9946e1a05e --- /dev/null +++ b/src/game/CalendarHandler.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "Player.h" +#include "WorldPacket.h" +#include "WorldSession.h" +#include "Opcodes.h" +#include "InstanceSaveMgr.h" + +void WorldSession::HandleCalendarGetCalendar(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GET_CALENDAR"); + recv_data.hexlike(); + + time_t cur_time = time(NULL); + + WorldPacket data(SMSG_CALENDAR_SEND_CALENDAR,4+4*0+4+4*0+4+4); + + // TODO: calendar invite event output + data << (uint32) 0; //invite node count + // TODO: calendar event output + data << (uint32) 0; //event count + + data << (uint32) 0; //wtf?? + data << (uint32) secsToTimeBitFields(cur_time); // current time + + uint32 counter = 0; + size_t p_counter = data.wpos(); + data << uint32(counter); // instance save count + + for(int i = 0; i < TOTAL_DIFFICULTIES; ++i) + { + for (Player::BoundInstancesMap::iterator itr = _player->m_boundInstances[i].begin(); itr != _player->m_boundInstances[i].end(); ++itr) + { + if(itr->second.perm) + { + InstanceSave *save = itr->second.save; + data << uint32(save->GetMapId()); + data << uint32(save->GetDifficulty()); + data << uint32(save->GetResetTime() - cur_time); + data << uint64(save->GetInstanceId()); // instance save id as unique instance copy id + ++counter; + } + } + } + data.put<uint32>(p_counter,counter); + + data << (uint32) 1135753200; //wtf?? (28.12.2005 12:00) + data << (uint32) 0; // unk counter 4 + data << (uint32) 0; // unk counter 5 + //sLog.outDebug("Sending calendar"); + //data.hexlike(); + SendPacket(&data); +} + +void WorldSession::HandleCalendarGetEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GET_EVENT"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarGuildFilter(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GUILD_FILTER"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarArenaTeam(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_ARENA_TEAM"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarAddEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_ADD_EVENT"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarUpdateEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_UPDATE_EVENT"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarRemoveEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_REMOVE_EVENT"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarCopyEvent(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_COPY_EVENT"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarEventInvite(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_INVITE"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarEventRsvp(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_RSVP"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarEventRemoveInvite(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_REMOVE_INVITE"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarEventStatus(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_STATUS"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarEventModeratorStatus(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_EVENT_MODERATOR_STATUS"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarComplain(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_COMPLAIN"); + recv_data.hexlike(); +} + +void WorldSession::HandleCalendarGetNumPending(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GET_NUM_PENDING"); + recv_data.hexlike(); + + WorldPacket data(SMSG_CALENDAR_SEND_NUM_PENDING, 4); + data << uint32(0); // 0 - no pending invites, 1 - some pending invites + SendPacket(&data); +} diff --git a/src/game/Cell.h b/src/game/Cell.h index 35bcdbeea8a..2459e3e73d2 100644 --- a/src/game/Cell.h +++ b/src/game/Cell.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -93,13 +93,13 @@ struct TRINITY_DLL_DECL Cell y = data.Part.grid_y*MAX_NUMBER_OF_CELLS + data.Part.cell_y; } - inline bool DiffCell(const Cell &cell) const + bool DiffCell(const Cell &cell) const { return( data.Part.cell_x != cell.data.Part.cell_x || data.Part.cell_y != cell.data.Part.cell_y ); } - inline bool DiffGrid(const Cell &cell) const + bool DiffGrid(const Cell &cell) const { return( data.Part.grid_x != cell.data.Part.grid_x || data.Part.grid_y != cell.data.Part.grid_y ); diff --git a/src/game/CellImpl.h b/src/game/CellImpl.h index ee026ec8353..0aea067b32b 100644 --- a/src/game/CellImpl.h +++ b/src/game/CellImpl.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Channel.cpp b/src/game/Channel.cpp index e05a9793857..992a20353ac 100644 --- a/src/game/Channel.cpp +++ b/src/game/Channel.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Channel.h b/src/game/Channel.h index b8d322ee9f7..b4fe04feb44 100644 --- a/src/game/Channel.h +++ b/src/game/Channel.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ChannelHandler.cpp b/src/game/ChannelHandler.cpp index ae869f36d4d..2fc634077c5 100644 --- a/src/game/ChannelHandler.cpp +++ b/src/game/ChannelHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ChannelMgr.h b/src/game/ChannelMgr.h index c31998c0569..a664e009b90 100644 --- a/src/game/ChannelMgr.h +++ b/src/game/ChannelMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 192e85a5347..ffdd9942bb5 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -64,11 +64,11 @@ bool LoginQueryHolder::Initialize() // NOTE: all fields in `characters` must be read to prevent lost character data at next save in case wrong DB structure. // !!! NOTE: including unused `zone`,`online` - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points,bgid,bgteam,bgmap,bgx,bgy,bgz,bgo FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT leaderGuid FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid)); - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,slot,active,disabled FROM character_spell WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS, "SELECT quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4 FROM character_queststatus WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,"SELECT quest,time FROM character_queststatus_daily WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADTUTORIALS, "SELECT tut0,tut1,tut2,tut3,tut4,tut5,tut6,tut7 FROM character_tutorial WHERE account = '%u' AND realmid = '%u'", GetAccountId(), realmID); @@ -85,6 +85,8 @@ bool LoginQueryHolder::Initialize() // in other case still be dummy query res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGUILD, "SELECT guildid,rank FROM guild_member WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADARENAINFO, "SELECT arenateamid, played_week, played_season, personal_rating FROM arena_team_member WHERE guid='%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS, "SELECT achievement, date FROM character_achievement WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS,"SELECT criteria, counter, date FROM character_achievement_progress WHERE guid = '%u'", GUID_LOPART(m_guid)); return res; } @@ -234,17 +236,16 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) if (raceEntry->addon > Expansion()) { data << (uint8)CHAR_CREATE_EXPANSION; - sLog.outError("Not Expansion 1 account:[%d] but tried to Create character with expansion 1 race (%u)",GetAccountId(),race_); + sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)",Expansion(),GetAccountId(),raceEntry->addon,race_); SendPacket( &data ); return; } // prevent character creating Expansion class without Expansion account - // TODO: use possible addon field in ChrClassesEntry in next dbc version - if (Expansion() < 2 && class_ == CLASS_DEATH_KNIGHT) + if (classEntry->addon > Expansion()) { - data << (uint8)CHAR_CREATE_EXPANSION; - sLog.outError("Not Expansion 2 account:[%d] but tried to Create character with expansion 2 class (%u)",GetAccountId(),class_); + data << (uint8)CHAR_CREATE_EXPANSION_CLASS; + sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)",Expansion(),GetAccountId(),classEntry->addon,class_); SendPacket( &data ); return; } @@ -311,29 +312,77 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) } } + // speedup check for heroic class disabled case + uint32 heroic_free_slots = sWorld.getConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM); + if(heroic_free_slots==0 && GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket( &data ); + return; + } + + // speedup check for heroic class disabled case + uint32 req_level_for_heroic = sWorld.getConfig(CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING); + if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT; + SendPacket( &data ); + return; + } + bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER; uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); bool have_same_race = false; - if(!AllowTwoSideAccounts || skipCinematics == 1) + + // if 0 then allowed creating without any characters + bool have_req_level_for_heroic = (req_level_for_heroic==0); + + if(!AllowTwoSideAccounts || skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) { - QueryResult *result2 = CharacterDatabase.PQuery("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1"); + QueryResult *result2 = CharacterDatabase.PQuery("SELECT guid,race,class FROM characters WHERE account = '%u' %s", + GetAccountId(), (skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) ? "" : "LIMIT 1"); if(result2) { uint32 team_= Player::TeamForRace(race_); Field* field = result2->Fetch(); - uint8 race = field[0].GetUInt32(); + uint8 acc_race = field[1].GetUInt32(); + + if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) + { + uint8 acc_class = field[2].GetUInt32(); + if(acc_class == CLASS_DEATH_KNIGHT) + { + if(heroic_free_slots > 0) + --heroic_free_slots; + + if(heroic_free_slots==0) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket( &data ); + return; + } + } + + if(!have_req_level_for_heroic) + { + uint32 acc_guid = field[0].GetUInt32(); + uint32 acc_level = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,acc_guid); + if(acc_level >= req_level_for_heroic) + have_req_level_for_heroic = true; + } + } // need to check team only for first character // TODO: what to if account already has characters of both races? if (!AllowTwoSideAccounts) { - uint32 team=0; - if(race > 0) - team = Player::TeamForRace(race); + uint32 acc_team=0; + if(acc_race > 0) + acc_team = Player::TeamForRace(acc_race); - if(team != team_) + if(acc_team != team_) { data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; SendPacket( &data ); @@ -342,20 +391,55 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) } } - if (skipCinematics == 1) + // search same race for cinematic or same class if need + // TODO: check if cinematic already shown? (already logged in?; cinematic field) + while ((skipCinematics == 1 && !have_same_race) || class_ == CLASS_DEATH_KNIGHT) { - // TODO: check if cinematic already shown? (already logged in?; cinematic field) - while (race_ != race && result2->NextRow()) + if(!result2->NextRow()) + break; + + field = result2->Fetch(); + acc_race = field[1].GetUInt32(); + + if(!have_same_race) + have_same_race = race_ == acc_race; + + if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) { - field = result2->Fetch(); - race = field[0].GetUInt32(); + uint8 acc_class = field[2].GetUInt32(); + if(acc_class == CLASS_DEATH_KNIGHT) + { + if(heroic_free_slots > 0) + --heroic_free_slots; + + if(heroic_free_slots==0) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket( &data ); + return; + } + } + + if(!have_req_level_for_heroic) + { + uint32 acc_guid = field[0].GetUInt32(); + uint32 acc_level = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL,acc_guid); + if(acc_level >= req_level_for_heroic) + have_req_level_for_heroic = true; + } } - have_same_race = race_ == race; } delete result2; } } + if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && !have_req_level_for_heroic) + { + data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT; + SendPacket( &data ); + return; + } + // extract other data required for player creating uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; recv_data >> gender >> skin >> face; @@ -514,9 +598,11 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) data << pCurrChar->GetOrientation(); SendPacket(&data); - data.Initialize( SMSG_ACCOUNT_DATA_TIMES, 128 ); - for(int i = 0; i < 32; i++) - data << uint32(0); + data.Initialize( SMSG_ACCOUNT_DATA_TIMES, 4+1+8*4 ); // changed in WotLK + data << uint32(time(NULL)); // unix time of something + data << uint8(1); + for(int i = 0; i < NUM_ACCOUNT_DATA_TYPES; i++) + data << uint32(GetAccountData(i)->Time); // also unix time SendPacket(&data); data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 @@ -619,17 +705,25 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) { pCurrChar->setCinematic(1); - ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace()); - if(rEntry) + if(ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->getClass())) { - data.Initialize( SMSG_TRIGGER_CINEMATIC,4 ); - data << uint32(rEntry->startmovie); - SendPacket( &data ); - + if(cEntry->CinematicSequence) + { + data.Initialize(SMSG_TRIGGER_CINEMATIC, 4); + data << uint32(cEntry->CinematicSequence); + SendPacket( &data ); + } + else if(ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace())) + { + data.Initialize(SMSG_TRIGGER_CINEMATIC, 4); + data << uint32(rEntry->CinematicSequence); + SendPacket( &data ); + } + // send new char string if not empty if (!sWorld.GetNewCharString().empty()) chH.PSendSysMessage(sWorld.GetNewCharString().c_str()); - } + } } if (!pCurrChar->GetMap()->Add(pCurrChar)) @@ -672,22 +766,6 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) - //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+41, 8326); - //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+42, 20584); - //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAFLAGS+6, 238); - //pCurrChar->SetUInt32Value(UNIT_FIELD_AURALEVELS+11, 514); - //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+11, 65535); - //pCurrChar->SetUInt32Value(UNIT_FIELD_DISPLAYID, 1825); - //if (pCurrChar->getRace() == RACE_NIGHTELF) - //{ - // pCurrChar->SetSpeed(MOVE_RUN, 1.5f*1.2f, true); - // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f*1.2f, true); - //} - //else - //{ - // pCurrChar->SetSpeed(MOVE_RUN, 1.5f, true); - // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f, true); - //} pCurrChar->SetMovement(MOVE_WATER_WALK); } @@ -747,7 +825,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) // Set FFA PvP for non GM in non-rest mode if(sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING) ) - pCurrChar->SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); if(pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) pCurrChar->SetContestedPvP(); @@ -917,11 +995,11 @@ void WorldSession::HandleToggleCloakOpcode( WorldPacket & /*recv_data*/ ) void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) { + CHECK_PACKET_SIZE(recv_data, 8+1); + uint64 guid; std::string newname; - CHECK_PACKET_SIZE(recv_data, 8+1); - recv_data >> guid; recv_data >> newname; @@ -929,15 +1007,15 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) if(!normalizePlayerName(newname)) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_NAME_NO_NAME; + data << uint8(CHAR_NAME_NO_NAME); SendPacket( &data ); return; } - if(!ObjectMgr::IsValidName(newname,true)) + if(!ObjectMgr::IsValidName(newname, true)) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_NAME_INVALID_CHARACTER; + data << uint8(CHAR_NAME_INVALID_CHARACTER); SendPacket( &data ); return; } @@ -946,7 +1024,7 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_NAME_RESERVED; + data << uint8(CHAR_NAME_RESERVED); SendPacket( &data ); return; } @@ -975,7 +1053,7 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uin if (!result) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_CREATE_ERROR; + data << uint8(CHAR_CREATE_ERROR); session->SendPacket( &data ); return; } @@ -989,11 +1067,11 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uin CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME), guidLow); CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", guidLow); - sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s",session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str()); + sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", session->GetAccountId(), session->GetRemoteAddress().c_str(), oldname.c_str(), guidLow, newname.c_str()); - WorldPacket data(SMSG_CHAR_RENAME,1+8+(newname.size()+1)); - data << (uint8)RESPONSE_SUCCESS; - data << guid; + WorldPacket data(SMSG_CHAR_RENAME, 1+8+(newname.size()+1)); + data << uint8(RESPONSE_SUCCESS); + data << uint64(guid); data << newname; session->SendPacket(&data); } @@ -1087,3 +1165,166 @@ void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data) data << uint64(guid); SendPacket(&data); } + +void WorldSession::HandleAlterAppearance( WorldPacket & recv_data ) +{ + sLog.outDebug("CMSG_ALTER_APPEARANCE"); + + CHECK_PACKET_SIZE(recv_data, 4+4+4); + + uint32 Hair, Color, FacialHair; + recv_data >> Hair >> Color >> FacialHair; + + BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair); + + if(!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->getGender()) + return; + + BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(FacialHair); + + if(!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->getGender()) + return; + + uint32 Cost = _player->GetBarberShopCost(bs_hair->hair_id, Color, bs_facialHair->hair_id); + + // 0 - ok + // 1,3 - not enough money + // 2 - you have to seat on barber chair + if(_player->GetMoney() < Cost) + { + WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4); + data << uint32(1); // no money + SendPacket(&data); + return; + } + else + { + WorldPacket data(SMSG_BARBER_SHOP_RESULT, 4); + data << uint32(0); // ok + SendPacket(&data); + } + + _player->SetMoney(_player->GetMoney() - Cost); // it isn't free + + _player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id)); + _player->SetByteValue(PLAYER_BYTES, 3, uint8(Color)); + _player->SetByteValue(PLAYER_BYTES_2, 0, uint8(bs_facialHair->hair_id)); + + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1); + + _player->SetStandState(0); // stand up +} + +void WorldSession::HandleRemoveGlyph( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 4); + + uint32 slot; + recv_data >> slot; + + if(slot > MAX_GLYPH_SLOT_INDEX) + { + sLog.outDebug("Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot); + return; + } + + if(uint32 glyph = _player->GetGlyph(slot)) + { + if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph)) + { + _player->RemoveAurasDueToSpell(gp->SpellId); + _player->SetGlyph(slot, 0); + } + } +} + +void WorldSession::HandleCharCustomize(WorldPacket& recv_data) +{ + CHECK_PACKET_SIZE(recv_data, 8+1); + + uint64 guid; + std::string newname; + + recv_data >> guid; + recv_data >> newname; + + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+1+1+1+1+1+1); + + uint8 gender, skin, face, hairStyle, hairColor, facialHair; + recv_data >> gender >> skin >> face >> hairStyle >> hairColor >> facialHair; + + QueryResult *result = CharacterDatabase.PQuery("SELECT at_login FROM characters WHERE guid ='%u'", GUID_LOPART(guid)); + if (!result) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_CREATE_ERROR); + SendPacket( &data ); + return; + } + + Field *fields = result->Fetch(); + uint32 at_loginFlags = fields[0].GetUInt32(); + delete result; + + if (!(at_loginFlags & AT_LOGIN_CUSTOMIZE)) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_CREATE_ERROR); + SendPacket( &data ); + return; + } + + // prevent character rename to invalid name + if(!normalizePlayerName(newname)) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_NAME_NO_NAME); + SendPacket( &data ); + return; + } + + if(!ObjectMgr::IsValidName(newname,true)) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_NAME_INVALID_CHARACTER); + SendPacket( &data ); + return; + } + + // check name limitations + if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(newname)) + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_NAME_RESERVED); + SendPacket( &data ); + return; + } + + if(objmgr.GetPlayerGUIDByName(newname)) // character with this name already exist + { + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1); + data << uint8(CHAR_CREATE_NAME_IN_USE); + SendPacket( &data ); + return; + } + + CharacterDatabase.escape_string(newname); + Player::Customize(guid, gender, skin, face, hairStyle, hairColor, facialHair); + CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_CUSTOMIZE), GUID_LOPART(guid)); + CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid)); + + std::string IP_str = GetRemoteAddress(); + sLog.outChar("Account: %d (IP: %s), Character guid: %u Customized to: %s", GetAccountId(), IP_str.c_str(), GUID_LOPART(guid), newname.c_str()); + + WorldPacket data(SMSG_CHAR_CUSTOMIZE, 1+8+(newname.size()+1)+6); + data << uint8(RESPONSE_SUCCESS); + data << uint64(guid); + data << newname; + data << uint8(gender); + data << uint8(skin); + data << uint8(face); + data << uint8(hairStyle); + data << uint8(hairColor); + data << uint8(facialHair); + SendPacket(&data); +} diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index fa2bc71152c..f64dd86545a 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,8 +33,26 @@ #include "MapManager.h" #include "GridNotifiersImpl.h" #include "CellImpl.h" +#include "AccountMgr.h" #include "TicketMgr.h" +// Supported shift-links (client generated and server side) +// |color|Harea:area_id|h[name]|h|r +// |color|Hcreature:creature_guid|h[name]|h|r +// |color|Hcreature_entry:creature_id|h[name]|h|r +// |color|Hgameevent:id|h[name]|h|r +// |color|Hgameobject:go_guid|h[name]|h|r +// |color|Hgameobject_entry:go_id|h[name]|h|r +// |color|Hitem:item_id:perm_ench_id:0:0|h[name]|h|r +// |color|Hitemset:itemset_id|h[name]|h|r +// |color|Hplayer:name|h[name]|h|r - client, in some messages, at click copy only name instead link +// |color|Hquest:quest_id|h[name]|h|r +// |color|Hskill:skill_id|h[name]|h|r +// |color|Hspell:spell_id|h[name]|h|r - client, spellbook spell icon shift-click +// |color|Htalent:talent_id,rank|h[name]|h|r - client, talent icon shift-click +// |color|Htele:id|h[name]|h|r +// |color|Htrade:spell_id,cur_value,max_value,unk3int,unk3str|h[name]|h|r - client, spellbook profession icon shift-click + bool ChatHandler::load_command_table = true; ChatCommand * ChatHandler::getCommandTable() @@ -112,6 +130,7 @@ ChatCommand * ChatHandler::getCommandTable() { "hp", SEC_MODERATOR, false, &ChatHandler::HandleModifyHPCommand, "", NULL }, { "mana", SEC_MODERATOR, false, &ChatHandler::HandleModifyManaCommand, "", NULL }, { "rage", SEC_MODERATOR, false, &ChatHandler::HandleModifyRageCommand, "", NULL }, + { "runicpower", SEC_MODERATOR, false, &ChatHandler::HandleModifyRunicPowerCommand, "", NULL }, { "energy", SEC_MODERATOR, false, &ChatHandler::HandleModifyEnergyCommand, "", NULL }, { "money", SEC_MODERATOR, false, &ChatHandler::HandleModifyMoneyCommand, "", NULL }, { "speed", SEC_MODERATOR, false, &ChatHandler::HandleModifySpeedCommand, "", NULL }, @@ -132,6 +151,7 @@ ChatCommand * ChatHandler::getCommandTable() { "drunk", SEC_MODERATOR, false, &ChatHandler::HandleDrunkCommand, "", NULL }, { "standstate", SEC_GAMEMASTER, false, &ChatHandler::HandleStandStateCommand, "", NULL }, { "morph", SEC_GAMEMASTER, false, &ChatHandler::HandleMorphCommand, "", NULL }, + { "phase", SEC_GAMEMASTER, false, &ChatHandler::HandleModifyPhaseCommand, "", NULL }, { "gender", SEC_ADMINISTRATOR, false, &ChatHandler::HandleModifyGenderCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; @@ -192,6 +212,7 @@ ChatCommand * ChatHandler::getCommandTable() { "sellerr", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSellErrorCommand, "", NULL }, { "buyerr", SEC_ADMINISTRATOR, false, &ChatHandler::HandleBuyErrorCommand, "", NULL }, { "sendopcode", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSendOpcodeCommand, "", NULL }, + { "spawnvehicle", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSpawnVehicle, "", NULL }, { "uws", SEC_ADMINISTRATOR, false, &ChatHandler::HandleUpdateWorldStateCommand, "", NULL }, { "ps", SEC_ADMINISTRATOR, false, &ChatHandler::HandlePlaySound2Command, "", NULL }, { "scn", SEC_ADMINISTRATOR, false, &ChatHandler::HandleSendChannelNotifyCommand, "", NULL }, @@ -205,6 +226,8 @@ ChatCommand * ChatHandler::getCommandTable() { "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleAnimCommand, "", NULL }, { "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleGetLootRecipient, "", NULL }, { "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL }, + { "bg", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugBattlegroundCommand, "", NULL }, + { "sendlargepacket",SEC_ADMINISTRATOR, false, &ChatHandler::HandleSendLargePacketCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; @@ -265,6 +288,7 @@ ChatCommand * ChatHandler::getCommandTable() { "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL }, { "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL }, { "trinity_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadTrinityStringCommand, "", NULL }, + { "milling_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesMillingCommand, "", NULL }, { "npc_gossip", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcGossipCommand, "", NULL }, { "npc_option", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcOptionCommand, "", NULL }, { "npc_trainer", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadNpcTrainerCommand, "", NULL }, @@ -286,8 +310,10 @@ ChatCommand * ChatHandler::getCommandTable() { "spell_required", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellRequiredCommand, "", NULL }, { "spell_elixir", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellElixirCommand, "", NULL }, { "spell_learn_spell", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellLearnSpellCommand, "", NULL }, + { "spell_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesSpellCommand, "", NULL }, { "spell_pet_auras", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellPetAurasCommand, "", NULL }, { "spell_proc_event", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellProcEventCommand, "", NULL }, + { "spell_bonus_data", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellBonusesCommand, "", NULL }, { "spell_script_target", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptTargetCommand, "", NULL }, { "spell_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellScriptsCommand, "", NULL }, { "spell_target_position", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSpellTargetPositionCommand, "", NULL }, @@ -302,7 +328,6 @@ ChatCommand * ChatHandler::getCommandTable() { "waypoint_scripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadWpScriptsCommand, "", NULL }, { "gm_tickets", SEC_ADMINISTRATOR, true, &ChatHandler::HandleGMTicketReloadCommand, "", NULL }, - { "", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; @@ -369,6 +394,7 @@ ChatCommand * ChatHandler::getCommandTable() static ChatCommand resetCommandTable[] = { + { "achievements", SEC_ADMINISTRATOR, false, &ChatHandler::HandleResetAchievementsCommand, "", NULL }, { "honor", SEC_ADMINISTRATOR, false, &ChatHandler::HandleResetHonorCommand, "", NULL }, { "level", SEC_ADMINISTRATOR, false, &ChatHandler::HandleResetLevelCommand, "", NULL }, { "spells", SEC_ADMINISTRATOR, false, &ChatHandler::HandleResetSpellsCommand, "", NULL }, @@ -435,6 +461,7 @@ ChatCommand * ChatHandler::getCommandTable() { "info", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcInfoCommand, "", NULL }, { "playemote", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNpcPlayEmoteCommand, "", NULL }, { "follow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcFollowCommand, "", NULL }, + { "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcSetPhaseCommand, "", NULL }, { "unfollow", SEC_GAMEMASTER, false, &ChatHandler::HandleNpcUnFollowCommand, "", NULL }, { "whisper", SEC_MODERATOR, false, &ChatHandler::HandleNpcWhisperCommand, "", NULL }, { "yell", SEC_MODERATOR, false, &ChatHandler::HandleNpcYellCommand, "", NULL }, @@ -468,12 +495,13 @@ ChatCommand * ChatHandler::getCommandTable() { { "add", SEC_GAMEMASTER, false, &ChatHandler::HandleGameObjectCommand, "", NULL }, { "delete", SEC_GAMEMASTER, false, &ChatHandler::HandleDelObjectCommand, "", NULL }, - { "target", SEC_GAMEMASTER, false, &ChatHandler::HandleTargetObjectCommand, "", NULL }, - { "turn", SEC_GAMEMASTER, false, &ChatHandler::HandleTurnObjectCommand, "", NULL }, { "move", SEC_GAMEMASTER, false, &ChatHandler::HandleMoveObjectCommand, "", NULL }, { "near", SEC_ADMINISTRATOR, false, &ChatHandler::HandleNearObjectCommand, "", NULL }, { "activate", SEC_GAMEMASTER, false, &ChatHandler::HandleActivateObjectCommand, "", NULL }, { "addtemp", SEC_GAMEMASTER, false, &ChatHandler::HandleTempGameObjectCommand, "", NULL }, + { "setphase", SEC_GAMEMASTER, false, &ChatHandler::HandleGOPhaseCommand, "", NULL }, + { "target", SEC_GAMEMASTER, false, &ChatHandler::HandleTargetObjectCommand, "", NULL }, + { "turn", SEC_GAMEMASTER, false, &ChatHandler::HandleTurnObjectCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; @@ -609,6 +637,7 @@ ChatCommand * ChatHandler::getCommandTable() { "sendmail", SEC_MODERATOR, true, &ChatHandler::HandleSendMailCommand, "", NULL }, { "sendmoney", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMoneyCommand, "", NULL }, { "rename", SEC_GAMEMASTER, true, &ChatHandler::HandleRenameCommand, "", NULL }, + { "customize", SEC_GAMEMASTER, true, &ChatHandler::HandleCustomizeCommand, "", NULL }, { "loadscripts", SEC_ADMINISTRATOR, true, &ChatHandler::HandleLoadScriptsCommand, "", NULL }, { "mute", SEC_GAMEMASTER, true, &ChatHandler::HandleMuteCommand, "", NULL }, { "unmute", SEC_GAMEMASTER, true, &ChatHandler::HandleUnmuteCommand, "", NULL }, @@ -686,6 +715,55 @@ bool ChatHandler::isAvailable(ChatCommand const& cmd) const return m_session->GetSecurity() >= cmd.SecurityLevel; } +bool ChatHandler::HasLowerSecurity(Player* target, uint64 guid, bool strong) +{ + WorldSession* target_session = NULL; + uint32 target_account = 0; + + if (target) + target_session = target->GetSession(); + else if (guid) + target_account = objmgr.GetPlayerAccountIdByGUID(guid); + + if(!target_session && !target_account) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return true; + } + + return HasLowerSecurityAccount(target_session,target_account,strong); +} + +bool ChatHandler::HasLowerSecurityAccount(WorldSession* target, uint32 target_account, bool strong) +{ + uint32 target_sec; + + // allow everything from console and RA console + if (!m_session) + return false; + + // ignore only for non-players for non strong checks (when allow apply command at least to same sec level) + if (m_session->GetSecurity() > SEC_PLAYER && !strong && !sWorld.getConfig(CONFIG_GM_LOWER_SECURITY)) + return false; + + if (target) + target_sec = target->GetSecurity(); + else if (target_account) + target_sec = accmgr.GetSecurity(target_account); + else + return true; // caller must report error for (target==NULL && target_account==0) + + if (m_session->GetSecurity() < target_sec || strong && m_session->GetSecurity() <= target_sec) + { + SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); + SetSentErrorMessage(true); + return true; + } + + return false; +} + bool ChatHandler::hasStringAbbr(const char* name, const char* part) { // non "" command @@ -771,9 +849,9 @@ void ChatHandler::PSendSysMessage(int32 entry, ...) { const char *format = GetTrinityString(entry); va_list ap; - char str [1024]; + char str [2048]; va_start(ap, entry); - vsnprintf(str,1024,format, ap ); + vsnprintf(str,2048,format, ap ); va_end(ap); SendSysMessage(str); } @@ -781,9 +859,9 @@ void ChatHandler::PSendSysMessage(int32 entry, ...) void ChatHandler::PSendSysMessage(const char *format, ...) { va_list ap; - char str [1024]; + char str [2048]; va_start(ap, format); - vsnprintf(str,1024,format, ap ); + vsnprintf(str,2048,format, ap ); va_end(ap); SendSysMessage(str); } @@ -1099,7 +1177,7 @@ Creature* ChatHandler::getSelectedCreature() if(!m_session) return NULL; - return ObjectAccessor::GetCreatureOrPet(*m_session->GetPlayer(),m_session->GetPlayer()->GetSelection()); + return ObjectAccessor::GetCreatureOrPetOrVehicle(*m_session->GetPlayer(),m_session->GetPlayer()->GetSelection()); } char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** something1) @@ -1170,12 +1248,23 @@ char* ChatHandler::extractKeyFromLink(char* text, char const* const* linkTypes, // [name] Shift-click form |color|linkType:key|h[name]|h|r // or // [name] Shift-click form |color|linkType:key:something1:...:somethingN|h[name]|h|r + // or + // [name] Shift-click form |linkType:key|h[name]|h|r - char* check = strtok(text, "|"); // skip color - if(!check) - return NULL; // end of data + char* tail; - char* cLinkType = strtok(NULL, ":"); // linktype + if(text[1]=='c') + { + char* check = strtok(text, "|"); // skip color + if(!check) + return NULL; // end of data + + tail = strtok(NULL, ""); // tail + } + else + tail = text+1; // skip first | + + char* cLinkType = strtok(tail, ":"); // linktype if(!cLinkType) return NULL; // end of data @@ -1251,8 +1340,8 @@ GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; - Trinity::GameObjectWithDbGUIDCheck go_check(*pl,lowguid); - Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(obj,go_check); + MaNGOS::GameObjectWithDbGUIDCheck go_check(*pl,lowguid); + MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(pl,obj,go_check); TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker); CellLock<GridReadGuard> cell_lock(cell, p); @@ -1262,9 +1351,18 @@ GameObject* ChatHandler::GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid return obj; } -static char const* const spellTalentKeys[] = { - "Hspell", - "Htalent", +enum SpellLinkType +{ + SPELL_LINK_SPELL = 0, + SPELL_LINK_TALENT = 1, + SPELL_LINK_TRADE = 2 +}; + +static char const* const spellKeys[] = +{ + "Hspell", // normal spell + "Htalent", // talent spell + "Htrade", // profession/skill spell 0 }; @@ -1272,31 +1370,41 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text) { // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r // number or [name] Shift-click form |color|Htalent:talent_id,rank|h[name]|h|r + // number or [name] Shift-click form |color|Htrade:spell_id,skill_id,max_value,cur_value|h[name]|h|r int type = 0; - char* rankS = NULL; - char* idS = extractKeyFromLink(text,spellTalentKeys,&type,&rankS); + char* param1_str = NULL; + char* idS = extractKeyFromLink(text,spellKeys,&type,¶m1_str); if(!idS) return 0; uint32 id = (uint32)atol(idS); - // spell - if(type==0) - return id; + switch(type) + { + case SPELL_LINK_SPELL: + return id; + case SPELL_LINK_TALENT: + { + // talent + TalentEntry const* talentEntry = sTalentStore.LookupEntry(id); + if(!talentEntry) + return 0; - // talent - TalentEntry const* talentEntry = sTalentStore.LookupEntry(id); - if(!talentEntry) - return 0; + int32 rank = param1_str ? (uint32)atol(param1_str) : 0; + if(rank >= 5) + return 0; - int32 rank = rankS ? (uint32)atol(rankS) : 0; - if(rank >= 5) - return 0; + if(rank < 0) + rank = 0; - if(rank < 0) - rank = 0; + return talentEntry->RankID[rank]; + } + case SPELL_LINK_TRADE: + return id; + } - return talentEntry->RankID[rank]; + // unknown type? + return 0; } GameTele const* ChatHandler::extractGameTeleFromLink(char* text) @@ -1314,9 +1422,84 @@ GameTele const* ChatHandler::extractGameTeleFromLink(char* text) return objmgr.GetGameTele(cId); } -const char *ChatHandler::GetName() const +enum GuidLinkType +{ + SPELL_LINK_PLAYER = 0, // must be first for selection in not link case + SPELL_LINK_CREATURE = 1, + SPELL_LINK_GAMEOBJECT = 2 +}; + +static char const* const guidKeys[] = +{ + "Hplayer", + "Hcreature", + "Hgameobject", + 0 +}; + +uint64 ChatHandler::extractGuidFromLink(char* text) { - return m_session->GetPlayer()->GetName(); + int type = 0; + + // |color|Hcreature:creature_guid|h[name]|h|r + // |color|Hgameobject:go_guid|h[name]|h|r + // |color|Hplayer:name|h[name]|h|r + char* idS = extractKeyFromLink(text,guidKeys,&type); + if(!idS) + return 0; + + switch(type) + { + case SPELL_LINK_PLAYER: + { + std::string name = idS; + if(!normalizePlayerName(name)) + return 0; + + if(Player* player = objmgr.GetPlayer(name.c_str())) + return player->GetGUID(); + + if(uint64 guid = objmgr.GetPlayerGUIDByName(name)) + return guid; + + return 0; + } + case SPELL_LINK_CREATURE: + { + uint32 lowguid = (uint32)atol(idS); + + if(CreatureData const* data = objmgr.GetCreatureData(lowguid) ) + return MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_UNIT); + else + return 0; + } + case SPELL_LINK_GAMEOBJECT: + { + uint32 lowguid = (uint32)atol(idS); + + if(GameObjectData const* data = objmgr.GetGOData(lowguid) ) + return MAKE_NEW_GUID(lowguid,data->id,HIGHGUID_GAMEOBJECT); + else + return 0; + } + } + + // unknown type? + return 0; +} + +std::string ChatHandler::extractPlayerNameFromLink(char* text) +{ + // |color|Hplayer:name|h[name]|h|r + char* name_str = extractKeyFromLink(text,"Hplayer"); + if(!name_str) + return ""; + + std::string name = name_str; + if(!normalizePlayerName(name)) + return ""; + + return name; } bool ChatHandler::needReportToTarget(Player* chr) const @@ -1342,7 +1525,7 @@ void CliHandler::SendSysMessage(const char *str) m_print("\r\n"); } -const char *CliHandler::GetName() const +std::string CliHandler::GetNameLink() const { return GetTrinityString(LANG_CONSOLE_COMMAND); } diff --git a/src/game/Chat.h b/src/game/Chat.h index 8329aab4d67..a24de275f78 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -72,8 +72,6 @@ class ChatHandler int ParseCommands(const char* text); - virtual char const* GetName() const; - protected: explicit ChatHandler() : m_session(NULL) {} // for CLI subclass @@ -81,6 +79,8 @@ class ChatHandler virtual bool isAvailable(ChatCommand const& cmd) const; virtual bool needReportToTarget(Player* chr) const; + bool HasLowerSecurity(Player* target, uint64 guid, bool strong = false); + bool HasLowerSecurityAccount(WorldSession* target, uint32 account, bool strong = false); void SendGlobalSysMessage(const char *str); void SendGlobalGMSysMessage(const char *str); @@ -166,6 +166,7 @@ class ChatHandler bool HandleModifyHPCommand(const char* args); bool HandleModifyManaCommand(const char* args); bool HandleModifyRageCommand(const char* args); + bool HandleModifyRunicPowerCommand(const char* args); bool HandleModifyEnergyCommand(const char* args); bool HandleModifyMoneyCommand(const char* args); bool HandleModifyASpeedCommand(const char* args); @@ -182,6 +183,7 @@ class ChatHandler bool HandleModifyHonorCommand (const char* args); bool HandleModifyRepCommand(const char* args); bool HandleModifyArenaCommand(const char* args); + bool HandleModifyPhaseCommand(const char* args); bool HandleModifyGenderCommand(const char* args); bool HandleNpcAddCommand(const char* args); @@ -197,6 +199,7 @@ class ChatHandler bool HandleNpcSayCommand(const char* args); bool HandleNpcSetModelCommand(const char* args); bool HandleNpcSetMoveTypeCommand(const char* args); + bool HandleNpcSetPhaseCommand(const char* args); bool HandleNpcSpawnDistCommand(const char* args); bool HandleNpcSpawnTimeCommand(const char* args); bool HandleNpcTameCommand(const char* args); @@ -206,7 +209,6 @@ class ChatHandler bool HandleNpcYellCommand(const char* args); bool HandleNpcAddFormationCommand(const char* args); - bool HandleReloadCommand(const char* args); bool HandleReloadAllCommand(const char* args); bool HandleReloadAllAreaCommand(const char* args); bool HandleReloadAllItemCommand(const char* args); @@ -237,11 +239,13 @@ class ChatHandler bool HandleReloadLootTemplatesFishingCommand(const char* args); bool HandleReloadLootTemplatesGameobjectCommand(const char* args); bool HandleReloadLootTemplatesItemCommand(const char* args); + bool HandleReloadLootTemplatesMillingCommand(const char* args); bool HandleReloadLootTemplatesPickpocketingCommand(const char* args); bool HandleReloadLootTemplatesProspectingCommand(const char* args); bool HandleReloadLootTemplatesReferenceCommand(const char* args); bool HandleReloadLootTemplatesQuestMailCommand(const char* args); bool HandleReloadLootTemplatesSkinningCommand(const char* args); + bool HandleReloadLootTemplatesSpellCommand(const char* args); bool HandleReloadTrinityStringCommand(const char* args); bool HandleReloadNpcGossipCommand(const char* args); bool HandleReloadNpcOptionCommand(const char* args); @@ -260,6 +264,7 @@ class ChatHandler bool HandleReloadSpellElixirCommand(const char* args); bool HandleReloadSpellLearnSpellCommand(const char* args); bool HandleReloadSpellProcEventCommand(const char* args); + bool HandleReloadSpellBonusesCommand(const char* args); bool HandleReloadSpellScriptTargetCommand(const char* args); bool HandleReloadSpellScriptsCommand(const char* args); bool HandleReloadSpellTargetPositionCommand(const char* args); @@ -321,6 +326,7 @@ class ChatHandler bool HandleTargetObjectCommand(const char* args); bool HandleDelObjectCommand(const char* args); bool HandleMoveObjectCommand(const char* args); + bool HandleGOPhaseCommand(const char* args); bool HandleTurnObjectCommand(const char* args); bool HandleObjectStateCommand(const char* args); bool HandlePInfoCommand(const char* args); @@ -401,6 +407,7 @@ class ChatHandler bool HandleDelTeleCommand(const char * args); bool HandleListAurasCommand(const char * args); + bool HandleResetAchievementsCommand(const char * args); bool HandleResetHonorCommand(const char * args); bool HandleResetLevelCommand(const char * args); bool HandleResetSpellsCommand(const char * args); @@ -452,6 +459,7 @@ class ChatHandler bool HandleSendChannelNotifyCommand(const char* args); bool HandleSendChatMsgCommand(const char* args); bool HandleRenameCommand(const char * args); + bool HandleCustomizeCommand(const char * args); bool HandleLoadPDumpCommand(const char *args); bool HandleWritePDumpCommand(const char *args); bool HandleCastCommand(const char *args); @@ -488,15 +496,26 @@ class ChatHandler bool HandleUnPossessCommand(const char* args); bool HandleBindSightCommand(const char* args); bool HandleUnbindSightCommand(const char* args); + bool HandleDebugBattlegroundCommand(const char * args); + bool HandleSpawnVehicle(const char * args); + bool HandleSendLargePacketCommand(const char * args); Player* getSelectedPlayer(); Creature* getSelectedCreature(); Unit* getSelectedUnit(); + char* extractKeyFromLink(char* text, char const* linkType, char** something1 = NULL); char* extractKeyFromLink(char* text, char const* const* linkTypes, int* found_idx, char** something1 = NULL); + uint32 extractSpellIdFromLink(char* text); + uint64 extractGuidFromLink(char* text); GameTele const* extractGameTeleFromLink(char* text); bool GetPlayerGroupAndGUIDByName(const char* cname, Player* &plr, Group* &group, uint64 &guid, bool offline = false); + std::string extractPlayerNameFromLink(char* text); + + std::string playerLink(std::string const& name) const { return m_session ? "|cffffffff|Hplayer:"+name+"|h["+name+"]|h|r" : name; } + virtual std::string GetNameLink() const { return GetNameLink(m_session->GetPlayer()); } + std::string GetNameLink(Player* chr) const { return playerLink(chr->GetName()); } GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(uint32 lowguid,uint32 entry); @@ -527,7 +546,7 @@ class CliHandler : public ChatHandler const char *GetTrinityString(int32 entry) const; bool isAvailable(ChatCommand const& cmd) const; void SendSysMessage(const char *str); - char const* GetName() const; + std::string GetNameLink() const; bool needReportToTarget(Player* chr) const; private: diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp index 7b5b552e74e..8a79dc42397 100644 --- a/src/game/ChatHandler.cpp +++ b/src/game/ChatHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -192,7 +192,7 @@ void WorldSession::HandleMessagechatOpcode( WorldPacket & recv_data ) Player *player = objmgr.GetPlayer(to.c_str()); uint32 tSecurity = GetSecurity(); - uint32 pSecurity = player ? player->GetSession()->GetSecurity() : 0; + uint32 pSecurity = player ? player->GetSession()->GetSecurity() : SEC_PLAYER; if(!player || tSecurity == SEC_PLAYER && pSecurity > SEC_PLAYER && !player->isAcceptWhispers()) { WorldPacket data(SMSG_CHAT_PLAYER_NOT_FOUND, (to.size()+1)); diff --git a/src/game/CombatHandler.cpp b/src/game/CombatHandler.cpp index 0ab8814fa29..1458af5fcef 100644 --- a/src/game/CombatHandler.cpp +++ b/src/game/CombatHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ConfusedMovementGenerator.cpp b/src/game/ConfusedMovementGenerator.cpp index ad8bab6e369..483c4979194 100644 --- a/src/game/ConfusedMovementGenerator.cpp +++ b/src/game/ConfusedMovementGenerator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ConfusedMovementGenerator.h b/src/game/ConfusedMovementGenerator.h index 8847460c504..2ad5990214f 100644 --- a/src/game/ConfusedMovementGenerator.h +++ b/src/game/ConfusedMovementGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp index 989ccd61151..75c89ba7287 100644 --- a/src/game/Corpse.cpp +++ b/src/game/Corpse.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,7 +36,7 @@ Corpse::Corpse(CorpseType type) : WorldObject() m_objectType |= TYPEMASK_CORPSE; m_objectTypeId = TYPEID_CORPSE; // 2.3.2 - 0x58 - m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION); m_valuesCount = CORPSE_END; @@ -71,26 +71,26 @@ bool Corpse::Create( uint32 guidlow ) return true; } -bool Corpse::Create( uint32 guidlow, Player *owner, uint32 mapid, float x, float y, float z, float ang ) +bool Corpse::Create( uint32 guidlow, Player *owner) { SetInstanceId(owner->GetInstanceId()); - WorldObject::_Create(guidlow, HIGHGUID_CORPSE, mapid); + WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetMapId(), owner->GetPhaseMask()); - Relocate(x,y,z,ang); + Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation()); if(!IsPositionValid()) { sLog.outError("ERROR: Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)", - guidlow,owner->GetName(),x,y); + guidlow,owner->GetName(),owner->GetPositionX(), owner->GetPositionY()); return false; } SetFloatValue( OBJECT_FIELD_SCALE_X, 1 ); - SetFloatValue( CORPSE_FIELD_POS_X, x ); - SetFloatValue( CORPSE_FIELD_POS_Y, y ); - SetFloatValue( CORPSE_FIELD_POS_Z, z ); - SetFloatValue( CORPSE_FIELD_FACING, ang ); + SetFloatValue( CORPSE_FIELD_POS_X, GetPositionX() ); + SetFloatValue( CORPSE_FIELD_POS_Y, GetPositionY() ); + SetFloatValue( CORPSE_FIELD_POS_Z, GetPositionZ() ); + SetFloatValue( CORPSE_FIELD_FACING, GetOrientation() ); SetUInt64Value( CORPSE_FIELD_OWNER, owner->GetGUID() ); m_grid = Trinity::ComputeGridPair(GetPositionX(), GetPositionY()); @@ -100,17 +100,18 @@ bool Corpse::Create( uint32 guidlow, Player *owner, uint32 mapid, float x, float void Corpse::SaveToDB() { - // prevent DB data inconsistance problems and duplicates + // prevent DB data inconsistence problems and duplicates CharacterDatabase.BeginTransaction(); DeleteFromDB(); std::ostringstream ss; - ss << "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance) VALUES (" + ss << "INSERT INTO corpse (guid,player,position_x,position_y,position_z,orientation,zone,map,data,time,corpse_type,instance,phaseMask) VALUES (" << GetGUIDLow() << ", " << GUID_LOPART(GetOwnerGUID()) << ", " << GetPositionX() << ", " << GetPositionY() << ", " << GetPositionZ() << ", " << GetOrientation() << ", " << GetZoneId() << ", " << GetMapId() << ", '"; for(uint16 i = 0; i < m_valuesCount; i++ ) ss << GetUInt32Value(i) << " "; - ss << "'," << uint64(m_time) <<", " << uint32(GetType()) << ", " << int(GetInstanceId()) << ")"; + ss << "'," << uint64(m_time) <<", " << uint32(GetType()) + << ", " << int(GetInstanceId()) << ", " << int(GetPhaseMask()) << ")"; CharacterDatabase.Execute( ss.str().c_str() ); CharacterDatabase.CommitTransaction(); } @@ -143,8 +144,8 @@ bool Corpse::LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId) { bool external = (result != NULL); if (!external) - // 0 1 2 3 4 5 6 7 8 - result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance FROM corpse WHERE guid = '%u'",guid); + // 0 1 2 3 4 5 6 7 8 9 + result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance,phaseMask FROM corpse WHERE guid = '%u'",guid); if( ! result ) { @@ -166,8 +167,8 @@ bool Corpse::LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId) bool Corpse::LoadFromDB(uint32 guid, Field *fields) { - // 0 1 2 3 4 5 6 7 8 - //result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance FROM corpse WHERE guid = '%u'",guid); + // 0 1 2 3 4 5 6 7 8 9 + //result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance,phaseMask FROM corpse WHERE guid = '%u'",guid); float positionX = fields[0].GetFloat(); float positionY = fields[1].GetFloat(); float positionZ = fields[2].GetFloat(); @@ -188,6 +189,7 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields) return false; } uint32 instanceid = fields[8].GetUInt32(); + uint32 phaseMask = fields[9].GetUInt32(); // overwrite possible wrong/corrupted guid SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_CORPSE)); @@ -195,6 +197,7 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields) // place SetInstanceId(instanceid); SetMapId(mapid); + SetPhaseMask(phaseMask,false); Relocate(positionX,positionY,positionZ,ort); if(!IsPositionValid()) diff --git a/src/game/Corpse.h b/src/game/Corpse.h index 3cd6299a494..45203a9de76 100644 --- a/src/game/Corpse.h +++ b/src/game/Corpse.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,7 +58,7 @@ class Corpse : public WorldObject void RemoveFromWorld(); bool Create( uint32 guidlow ); - bool Create( uint32 guidlow, Player *owner, uint32 mapid, float x, float y, float z, float ang ); + bool Create( uint32 guidlow, Player *owner ); void SaveToDB(); bool LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 681aab3ebe3..9a4b35f21f7 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -39,7 +39,7 @@ #include "SpellAuras.h" #include "WaypointMovementGenerator.h" #include "InstanceData.h" -#include "BattleGround.h" +#include "BattleGroundMgr.h" #include "Util.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" @@ -55,7 +55,7 @@ void TrainerSpellData::Clear() { for (TrainerSpellList::iterator itr = spellList.begin(); itr != spellList.end(); ++itr) delete (*itr); - spellList.empty(); + spellList.clear(); } TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const @@ -145,14 +145,15 @@ Unit(), i_AI(NULL), i_AI_possessed(NULL), lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0), m_lootMoney(0), m_lootRecipient(0), m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f), -m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false), m_reactState(REACT_AGGRESSIVE), -m_regenTimer(2000), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0), +m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false), m_isVehicle(false), m_reactState(REACT_AGGRESSIVE), +m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0), m_AlreadyCallAssistance(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),m_creatureInfo(NULL), m_DBTableGuid(0), m_formationID(0) { + m_regenTimer = 200; m_valuesCount = UNIT_END; - for(int i =0; i<4; ++i) + for(int i =0; i<CREATURE_MAX_SPELLS; ++i) m_spells[i] = 0; m_CreatureSpellCooldowns.clear(); @@ -316,7 +317,6 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data ) // creatures always have melee weapon ready if any SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_AURAS ); SelectLevel(GetCreatureInfo()); if (team == HORDE) @@ -360,10 +360,8 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data ) SetPvP(true); } - m_spells[0] = GetCreatureInfo()->spell1; - m_spells[1] = GetCreatureInfo()->spell2; - m_spells[2] = GetCreatureInfo()->spell3; - m_spells[3] = GetCreatureInfo()->spell4; + for(int i=0; i < CREATURE_MAX_SPELLS; ++i) + m_spells[i] = GetCreatureInfo()->spells[i]; // HACK: trigger creature is always not selectable if(isTrigger()) @@ -637,11 +635,11 @@ void Creature::DisablePossessedAI() m_AI_enabled = true; } -bool Creature::Create (uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data) +bool Creature::Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 team, const CreatureData *data) { SetMapId(map->GetId()); SetInstanceId(map->GetInstanceId()); - //m_DBTableGuid = guidlow; + SetPhaseMask(phaseMask,false); //oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0; const bool bResult = CreateFromProto(guidlow, Entry, team, data); @@ -762,7 +760,7 @@ bool Creature::isCanInteractWithBattleMaster(Player* pPlayer, bool msg) const if(!isBattleMaster()) return false; - uint32 bgTypeId = objmgr.GetBattleMasterBG(GetEntry()); + BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(GetEntry()); if(!msg) return pPlayer->GetBGAccessByLevel(bgTypeId); @@ -778,8 +776,11 @@ bool Creature::isCanInteractWithBattleMaster(Player* pPlayer, bool msg) const case BATTLEGROUND_NA: case BATTLEGROUND_BE: case BATTLEGROUND_AA: - case BATTLEGROUND_RL: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break; - break; + case BATTLEGROUND_RL: + case BATTLEGROUND_SA: + case BATTLEGROUND_DS: + case BATTLEGROUND_RV: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break; + default: break; } return false; } @@ -926,13 +927,11 @@ void Creature::sendPreparedGossip(Player* player) if(!player) return; - GossipMenu& gossipmenu = player->PlayerTalkClass->GetGossipMenu(); - if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_WORLDEVENT) // if world event npc then gameeventmgr.HandleWorldEventGossip(player, this); // update world state with progress // in case empty gossip menu open quest menu if any - if (gossipmenu.Empty() && GetNpcTextId() == 0) + if (player->PlayerTalkClass->GetGossipMenu().Empty() && !player->PlayerTalkClass->GetQuestMenu().Empty()) { player->SendPreparedQuest(GetGUID()); return; @@ -1033,7 +1032,7 @@ void Creature::OnGossipSelect(Player* player, uint32 option) break; case GOSSIP_OPTION_BATTLEFIELD: { - uint32 bgTypeId = objmgr.GetBattleMasterBG(GetEntry()); + BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(GetEntry()); player->GetSession()->SendBattlegGroundList( GetGUID(), bgTypeId ); break; } @@ -1196,10 +1195,10 @@ void Creature::SaveToDB() return; } - SaveToDB(GetMapId(), data->spawnMask); + SaveToDB(GetMapId(), data->spawnMask,GetPhaseMask()); } -void Creature::SaveToDB(uint32 mapid, uint8 spawnMask) +void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) { // update in loaded data if (!m_DBTableGuid) @@ -1219,6 +1218,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask) // data->guid = guid don't must be update at save data.id = GetEntry(); data.mapid = mapid; + data.phaseMask = phaseMask; data.displayid = displayId; data.equipmentId = GetEquipmentId(); data.posX = GetPositionX(); @@ -1248,6 +1248,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask) << GetEntry() << "," << mapid <<"," << (uint32)spawnMask << "," + << (uint32)GetPhaseMask() << "," << displayId <<"," << GetEquipmentId() <<"," << GetPositionX() << "," @@ -1417,7 +1418,7 @@ bool Creature::LoadFromDB(uint32 guid, Map *map) if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_UNIT); uint16 team = 0; - if(!Create(guid,map,data->id,team,data)) + if(!Create(guid,map,data->phaseMask,data->id,team,data)) return false; Relocate(data->posX,data->posY,data->posZ,data->orientation); @@ -1478,11 +1479,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force) if (force) { for (uint8 i = 0; i < 3; i++) - { - SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, 0); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), 0); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, 0); - } + SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, 0); m_equipmentId = 0; } return; @@ -1494,11 +1491,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force) m_equipmentId = equip_entry; for (uint8 i = 0; i < 3; i++) - { - SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, einfo->equipmodel[i]); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), einfo->equipinfo[i]); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, einfo->equipslot[i]); - } + SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, einfo->equipentry[i]); } bool Creature::hasQuest(uint32 quest_id) const @@ -1556,6 +1549,10 @@ bool Creature::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList, bo if (u == this) return true; + // phased visibility (both must phased in same way) + if(!InSamePhase(u)) + return false; + // always seen by owner if(GetGUID() == u->GetCharmerOrOwnerGUID()) return true; @@ -1726,7 +1723,7 @@ void Creature::Respawn() } } -bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) +bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo) { if (!spellInfo) return false; @@ -1734,15 +1731,15 @@ bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) if (GetCreatureInfo()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1))) return true; - return Unit::IsImmunedToSpell(spellInfo, useCharges); + return Unit::IsImmunedToSpell(spellInfo); } -bool Creature::IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const +bool Creature::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const { - if (GetCreatureInfo()->MechanicImmuneMask & (1 << (mechanic-1))) + if (GetCreatureInfo()->MechanicImmuneMask & (1 << (spellInfo->EffectMechanic[index] - 1))) return true; - return Unit::IsImmunedToSpellEffect(effect, mechanic); + return Unit::IsImmunedToSpellEffect(spellInfo, index); } SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim) @@ -1786,7 +1783,9 @@ SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim) // continue; if( dist > range || dist < minrange ) continue; - if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + continue; + if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) continue; return spellInfo; } @@ -1830,7 +1829,9 @@ SpellEntry const *Creature::reachWithSpellCure(Unit *pVictim) // continue; if( dist > range || dist < minrange ) continue; - if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + continue; + if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) continue; return spellInfo; } @@ -1878,7 +1879,7 @@ void Creature::DoFleeToGetAssistance(float radius) // Optional parameter Creature* pCreature = NULL; Trinity::NearestAssistCreatureInCreatureRangeCheck u_check(this,getVictim(),radius); - Trinity::CreatureLastSearcher<Trinity::NearestAssistCreatureInCreatureRangeCheck> searcher(pCreature, u_check); + Trinity::CreatureLastSearcher<Trinity::NearestAssistCreatureInCreatureRangeCheck> searcher(this, pCreature, u_check); VisitNearbyGridObject(radius, searcher); if(!pCreature) @@ -1898,7 +1899,7 @@ Unit* Creature::SelectNearestTarget(float dist) const { Trinity::NearestHostileUnitInAttackDistanceCheck u_check(this, dist); - Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck> searcher(target, u_check); + Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck> searcher(this, target, u_check); TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); @@ -1928,8 +1929,8 @@ void Creature::CallAssistance() cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - Trinity::AnyAssistCreatureInRangeCheck u_check(this, getVictim(), radius); - Trinity::CreatureListSearcher<Trinity::AnyAssistCreatureInRangeCheck> searcher(assistList, u_check); + MaNGOS::AnyAssistCreatureInRangeCheck u_check(this, getVictim(), radius); + MaNGOS::CreatureListSearcher<MaNGOS::AnyAssistCreatureInRangeCheck> searcher(this, assistList, u_check); TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AnyAssistCreatureInRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher); diff --git a/src/game/Creature.h b/src/game/Creature.h index 97796f3e639..e79164bfed6 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -176,7 +176,7 @@ struct CreatureInfo uint32 rangeattacktime; uint32 unit_flags; // enum UnitFlags mask values uint32 dynamicflags; - uint32 family; // enum CreatureFamily values for type==CREATURE_TYPE_BEAST, or 0 in another cases + uint32 family; // enum CreatureFamily values (optional) uint32 trainer_type; uint32 trainer_spell; uint32 classNum; @@ -195,10 +195,7 @@ struct CreatureInfo int32 resistance4; int32 resistance5; int32 resistance6; - uint32 spell1; - uint32 spell2; - uint32 spell3; - uint32 spell4; + uint32 spells[CREATURE_MAX_SPELLS]; uint32 PetSpellDataId; uint32 mingold; uint32 maxgold; @@ -221,6 +218,8 @@ struct CreatureInfo return SKILL_HERBALISM; else if(type_flags & CREATURE_TYPEFLAGS_MININGLOOT) return SKILL_MINING; + else if(type_flags & CREATURE_TYPEFLAGS_ENGINEERLOOT) + return SKILL_ENGINERING; else return SKILL_SKINNING; // normal case } @@ -246,9 +245,7 @@ struct NpcOptionLocale struct EquipmentInfo { uint32 entry; - uint32 equipmodel[3]; - uint32 equipinfo[3]; - uint32 equipslot[3]; + uint32 equipentry[3]; }; // from `creature` table @@ -256,6 +253,7 @@ struct CreatureData { uint32 id; // entry in creature_template uint16 mapid; + uint16 phaseMask; uint32 displayid; int32 equipmentId; float posX; @@ -352,6 +350,7 @@ struct VendorItemData { for (VendorItemList::iterator itr = m_items.begin(); itr != m_items.end(); ++itr) delete (*itr); + m_items.clear(); } }; @@ -370,10 +369,14 @@ typedef std::list<VendorItemCount> VendorItemCounts; struct TrainerSpell { uint32 spell; - uint32 spellcost; - uint32 reqskill; - uint32 reqskillvalue; - uint32 reqlevel; + uint32 spellCost; + uint32 reqSkill; + uint32 reqSkillValue; + uint32 reqLevel; + uint32 learnedSpell; + + // helpers + bool IsCastable() const { return learnedSpell != spell; } }; typedef std::vector<TrainerSpell*> TrainerSpellList; @@ -412,7 +415,7 @@ class TRINITY_DLL_SPEC Creature : public Unit void AddToWorld(); void RemoveFromWorld(); - bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data = NULL); + bool Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 team, const CreatureData *data = NULL); bool LoadCreaturesAddon(bool reload = false); void SelectLevel(const CreatureInfo *cinfo); void LoadEquipment(uint32 equip_entry, bool force=false); @@ -425,6 +428,7 @@ class TRINITY_DLL_SPEC Creature : public Unit uint32 GetEquipmentId() const { return m_equipmentId; } bool isPet() const { return m_isPet; } + bool isVehicle() const { return m_isVehicle; } void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; } bool isTotem() const { return m_isTotem; } bool isRacialLeader() const { return GetCreatureInfo()->RacialLeader; } @@ -441,9 +445,9 @@ class TRINITY_DLL_SPEC Creature : public Unit bool isCanInteractWithBattleMaster(Player* player, bool msg) const; bool isCanTrainingAndResetTalentsOf(Player* pPlayer) const; bool IsOutOfThreatArea(Unit* pVictim) const; - bool IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges = false); + bool IsImmunedToSpell(SpellEntry const* spellInfo); // redefine Unit::IsImmunedToSpell - bool IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const; + bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const; // redefine Unit::IsImmunedToSpellEffect bool isElite() const { @@ -544,7 +548,7 @@ class TRINITY_DLL_SPEC Creature : public Unit bool LoadFromDB(uint32 guid, Map *map); void SaveToDB(); // overwrited in Pet - virtual void SaveToDB(uint32 mapid, uint8 spawnMask); + virtual void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask); virtual void DeleteFromDB(); // overwrited in Pet Loot loot; @@ -660,11 +664,11 @@ class TRINITY_DLL_SPEC Creature : public Unit uint8 m_emoteState; bool m_isPet; // set only in Pet::Pet + bool m_isVehicle; // set only in Vehicle::Vehicle bool m_isTotem; // set only in Totem::Totem ReactStates m_reactState; // for AI, not charmInfo void RegenerateMana(); void RegenerateHealth(); - uint32 m_regenTimer; MovementGeneratorType m_defaultMovementType; Cell m_currentCell; // store current cell where creature listed uint32 m_DBTableGuid; ///< For new or temporary creatures is 0 for saved it is lowguid diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index 885d9ddcadb..7343bb8333a 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index c39fb6ce9dd..4e0051c3d0c 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/CreatureAIImpl.h b/src/game/CreatureAIImpl.h index 2122adeb61c..cb422c2a016 100644 --- a/src/game/CreatureAIImpl.h +++ b/src/game/CreatureAIImpl.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/CreatureAIRegistry.cpp b/src/game/CreatureAIRegistry.cpp index 12b4aa97d0d..9ed1763141f 100644 --- a/src/game/CreatureAIRegistry.cpp +++ b/src/game/CreatureAIRegistry.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/CreatureAIRegistry.h b/src/game/CreatureAIRegistry.h index 0fecef476dc..53776e3d4e9 100644 --- a/src/game/CreatureAIRegistry.h +++ b/src/game/CreatureAIRegistry.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/CreatureAISelector.cpp b/src/game/CreatureAISelector.cpp index bebc810e6c0..8b4205980be 100644 --- a/src/game/CreatureAISelector.cpp +++ b/src/game/CreatureAISelector.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/CreatureAISelector.h b/src/game/CreatureAISelector.h index 8a354a4007e..a6fc47e3913 100644 --- a/src/game/CreatureAISelector.h +++ b/src/game/CreatureAISelector.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/CreatureGroups.cpp b/src/game/CreatureGroups.cpp index 3669c638c45..a45c59f9186 100644 --- a/src/game/CreatureGroups.cpp +++ b/src/game/CreatureGroups.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/CreatureGroups.h b/src/game/CreatureGroups.h index c8dd45c1b3f..45df16086b1 100644 --- a/src/game/CreatureGroups.h +++ b/src/game/CreatureGroups.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Debugcmds.cpp b/src/game/Debugcmds.cpp index daa8a2f8fa3..60f1536963f 100644 --- a/src/game/Debugcmds.cpp +++ b/src/game/Debugcmds.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -63,6 +63,7 @@ bool ChatHandler::HandleDebugSpellFailCommand(const char* args) uint8 failnum = (uint8)atoi(px); WorldPacket data(SMSG_CAST_FAILED, 5); + data << uint8(0); data << uint32(133); data << uint8(failnum); m_session->SendPacket(&data); @@ -132,8 +133,12 @@ bool ChatHandler::HandleBuyErrorCommand(const char* args) bool ChatHandler::HandleSendOpcodeCommand(const char* /*args*/) { Unit *unit = getSelectedUnit(); + Player *player = NULL; if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) - unit = m_session->GetPlayer(); + player = m_session->GetPlayer(); + else + player = (Player*)unit; + if(!unit) unit = player; std::ifstream ifs("opcode.txt"); if(ifs.bad()) @@ -192,6 +197,14 @@ bool ChatHandler::HandleSendOpcodeCommand(const char* /*args*/) { data.append(unit->GetPackGUID()); } + else if(type == "myguid") + data.append(player->GetPackGUID()); + else if(type == "pos") + { + data << unit->GetPositionX(); + data << unit->GetPositionY(); + data << unit->GetPositionZ(); + } else { sLog.outDebug("Sending opcode: unknown type '%s'", type.c_str()); @@ -201,7 +214,7 @@ bool ChatHandler::HandleSendOpcodeCommand(const char* /*args*/) ifs.close(); sLog.outDebug("Sending opcode %u", data.GetOpcode()); data.hexlike(); - ((Player*)unit)->GetSession()->SendPacket(&data); + player->GetSession()->SendPacket(&data); PSendSysMessage(LANG_COMMAND_OPCODESENT, data.GetOpcode(), unit->GetName()); return true; } @@ -522,6 +535,12 @@ bool ChatHandler::HandleGetItemState(const char* args) return true; } +bool ChatHandler::HandleDebugBattlegroundCommand(const char * /*args*/) +{ + sBattleGroundMgr.ToggleTesting(); + return true; +} + bool ChatHandler::HandleDebugArenaCommand(const char * /*args*/) { sBattleGroundMgr.ToggleArenaTesting(); @@ -570,3 +589,63 @@ bool ChatHandler::HandleDebugHostilRefList(const char * /*args*/) SendSysMessage("End of hostil reference list."); return true; } + +bool ChatHandler::HandleSpawnVehicle(const char* args) +{ + if(!args) + return false; + + char* e = strtok((char*)args, " "); + char* i = strtok(NULL, " "); + + if (!e || !i) + return false; + + uint32 entry = (uint32)atoi(e); + uint32 id = (uint32)atoi(i); + + CreatureInfo const *ci = objmgr.GetCreatureTemplate(entry); + + if(!ci) + return false; + + VehicleEntry const *ve = sVehicleStore.LookupEntry(id); + + if(!ve) + return false; + + Vehicle *v = new Vehicle; + Map *map = m_session->GetPlayer()->GetMap(); + if(!v->Create(objmgr.GenerateLowGuid(HIGHGUID_VEHICLE), map, entry, id, m_session->GetPlayer()->GetTeam())) + { + delete v; + return false; + } + + float px, py, pz; + m_session->GetPlayer()->GetClosePoint(px, py, pz, m_session->GetPlayer()->GetObjectSize()); + + v->Relocate(px, py, pz, m_session->GetPlayer()->GetOrientation()); + + if(!v->IsPositionValid()) + { + sLog.outError("ERROR: Vehicle (guidlow %d, entry %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + v->GetGUIDLow(), v->GetEntry(), v->GetPositionX(), v->GetPositionY()); + delete v; + return false; + } + + map->Add((Creature*)v); + + return true; +} + +bool ChatHandler::HandleSendLargePacketCommand(const char* args) +{ + const char* stuffingString = "This is a dummy string to push the packet's size beyond 128000 bytes. "; + std::ostringstream ss; + while(strlen(ss.str().c_str()) < 128000) + ss << stuffingString; + SendSysMessage(ss.str().c_str()); + return true; +} diff --git a/src/game/DestinationHolder.cpp b/src/game/DestinationHolder.cpp index 1a9beab4a01..6f4e08256c5 100644 --- a/src/game/DestinationHolder.cpp +++ b/src/game/DestinationHolder.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/DestinationHolder.h b/src/game/DestinationHolder.h index 311fb4f4d70..a1d295ead09 100644 --- a/src/game/DestinationHolder.h +++ b/src/game/DestinationHolder.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/DestinationHolderImp.h b/src/game/DestinationHolderImp.h index 443f6a90211..963e074fff9 100644 --- a/src/game/DestinationHolderImp.h +++ b/src/game/DestinationHolderImp.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/DuelHandler.cpp b/src/game/DuelHandler.cpp index bc3cf7db4bf..acde3b4ef51 100644 --- a/src/game/DuelHandler.cpp +++ b/src/game/DuelHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp index 4f63a149244..09856f1233e 100644 --- a/src/game/DynamicObject.cpp +++ b/src/game/DynamicObject.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,7 +38,7 @@ DynamicObject::DynamicObject() : WorldObject() m_objectType |= TYPEMASK_DYNAMICOBJECT; m_objectTypeId = TYPEID_DYNAMICOBJECT; // 2.3.2 - 0x58 - m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION); m_valuesCount = DYNAMICOBJECT_END; } @@ -61,7 +61,7 @@ bool DynamicObject::Create( uint32 guidlow, Unit *caster, uint32 spellId, uint32 { SetInstanceId(caster->GetInstanceId()); - WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetMapId()); + WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetMapId(), caster->GetPhaseMask()); Relocate(x,y,z,0); if(!IsPositionValid()) diff --git a/src/game/DynamicObject.h b/src/game/DynamicObject.h index a27be9a521c..05a5f3d930d 100644 --- a/src/game/DynamicObject.h +++ b/src/game/DynamicObject.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/FleeingMovementGenerator.cpp b/src/game/FleeingMovementGenerator.cpp index ff3d2f21b78..a3bbb965961 100644 --- a/src/game/FleeingMovementGenerator.cpp +++ b/src/game/FleeingMovementGenerator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -301,19 +301,26 @@ FleeingMovementGenerator<T>::Initialize(T &owner) if(!&owner) return; - Unit * fright = ObjectAccessor::GetUnit(owner, i_frightGUID); - if(!fright) - return; - _Init(owner); owner.CastStop(); owner.addUnitState(UNIT_STAT_FLEEING); owner.SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING); owner.SetUInt64Value(UNIT_FIELD_TARGET, 0); owner.RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - i_caster_x = fright->GetPositionX(); - i_caster_y = fright->GetPositionY(); - i_caster_z = fright->GetPositionZ(); + + if(Unit * fright = ObjectAccessor::GetUnit(owner, i_frightGUID)) + { + i_caster_x = fright->GetPositionX(); + i_caster_y = fright->GetPositionY(); + i_caster_z = fright->GetPositionZ(); + } + else + { + i_caster_x = owner.GetPositionX(); + i_caster_y = owner.GetPositionY(); + i_caster_z = owner.GetPositionZ(); + } + i_only_forward = true; i_cur_angle = 0.0f; i_last_distance_from_caster = 0.0f; diff --git a/src/game/FleeingMovementGenerator.h b/src/game/FleeingMovementGenerator.h index 23b5a0ad589..9bf967fa42d 100644 --- a/src/game/FleeingMovementGenerator.h +++ b/src/game/FleeingMovementGenerator.h @@ -1,7 +1,7 @@ /* -* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * -* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/FollowerRefManager.h b/src/game/FollowerRefManager.h index ab445fa29df..06e04c8d3ae 100644 --- a/src/game/FollowerRefManager.h +++ b/src/game/FollowerRefManager.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/FollowerReference.cpp b/src/game/FollowerReference.cpp index c554f6b44ba..d6a113a8bb6 100644 --- a/src/game/FollowerReference.cpp +++ b/src/game/FollowerReference.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/FollowerReference.h b/src/game/FollowerReference.h index 1a7c09d13e9..d15664ab6db 100644 --- a/src/game/FollowerReference.h +++ b/src/game/FollowerReference.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Formulas.h b/src/game/Formulas.h index f9915a2001c..720a7a2825d 100644 --- a/src/game/Formulas.h +++ b/src/game/Formulas.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -80,8 +80,17 @@ namespace Trinity inline uint32 BaseGain(uint32 pl_level, uint32 mob_level, ContentLevels content) { - //TODO: need modifier for CONTENT_71_80 different from CONTENT_61_70? - const uint32 nBaseExp = content == CONTENT_1_60 ? 45 : 235; + uint32 nBaseExp; + switch(content) + { + case CONTENT_1_60: nBaseExp = 45; break; + case CONTENT_61_70: nBaseExp = 235; break; + case CONTENT_71_80: nBaseExp = 580; break; + default: + sLog.outError("BaseGain: Unsupported content level %u",content); + nBaseExp = 45; break; + } + if( mob_level >= pl_level ) { uint32 nLevelDiff = mob_level - pl_level; @@ -118,66 +127,6 @@ namespace Trinity return (uint32)(xp_gain*sWorld.getRate(RATE_XP_KILL)); } - inline uint32 xp_Diff(uint32 lvl) - { - if( lvl < 29 ) - return 0; - if( lvl == 29 ) - return 1; - if( lvl == 30 ) - return 3; - if( lvl == 31 ) - return 6; - else - return (5*(lvl-30)); - } - - inline uint32 mxp(uint32 lvl) - { - if (lvl < 60) - { - return (45 + (5*lvl)); - } - else - { - return (235 + (5*lvl)); - } - } - - inline uint32 xp_to_level(uint32 lvl) - { - uint32 xp = 0; - if (lvl < 60) - { - xp = (8*lvl + xp_Diff(lvl)) * mxp(lvl); - } - else if (lvl == 60) - { - xp = (155 + mxp(lvl) * (1344 - 70 - ((69 - lvl) * (7 + (69 - lvl) * 8 - 1)/2))); - } - else if (lvl < 70) - { - xp = (155 + mxp(lvl) * (1344 - ((69-lvl) * (7 + (69 - lvl) * 8 - 1)/2))); - }else - { - // level higher than 70 is not supported - xp = (uint32)(779700 * (pow(sWorld.getRate(RATE_XP_PAST_70), (int32)lvl - 69))); - return ((xp < 0x7fffffff) ? xp : 0x7fffffff); - } - - // The XP to Level is always rounded to the nearest 100 points (50 rounded to high). - xp = ((xp + 50) / 100) * 100; // use additional () for prevent free association operations in C++ - - if ((lvl > 10) && (lvl < 60)) // compute discount added in 2.3.x - { - uint32 discount = (lvl < 28) ? (lvl - 10) : 18; - xp = (xp * (100 - discount)) / 100; // apply discount - xp = (xp / 100) * 100; // floor to hundreds - } - - return xp; - } - inline float xp_in_group_rate(uint32 count, bool isRaid) { if(isRaid) diff --git a/src/game/GameEvent.cpp b/src/game/GameEvent.cpp index ee6f348296a..62f285e25ac 100644 --- a/src/game/GameEvent.cpp +++ b/src/game/GameEvent.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -190,50 +190,52 @@ void GameEvent::LoadFromDB() if( !result ) { mGameEvent.clear(); - sLog.outString(">> Table game_event is empty:"); + sLog.outString(">> Table game_event is empty!"); sLog.outString(); return; } uint32 count = 0; - barGoLink bar( result->GetRowCount() ); - do { - ++count; - Field *fields = result->Fetch(); + barGoLink bar( result->GetRowCount() ); + do + { + ++count; + Field *fields = result->Fetch(); - bar.step(); + bar.step(); - uint16 event_id = fields[0].GetUInt16(); - if(event_id==0) - { - sLog.outErrorDb("`game_event` game event id (%i) is reserved and can't be used.",event_id); - continue; - } + uint16 event_id = fields[0].GetUInt16(); + if(event_id==0) + { + sLog.outErrorDb("`game_event` game event id (%i) is reserved and can't be used.",event_id); + continue; + } - GameEventData& pGameEvent = mGameEvent[event_id]; - uint64 starttime = fields[1].GetUInt64(); - pGameEvent.start = time_t(starttime); - uint64 endtime = fields[2].GetUInt64(); - pGameEvent.end = time_t(endtime); - pGameEvent.occurence = fields[3].GetUInt32(); - pGameEvent.length = fields[4].GetUInt32(); - pGameEvent.description = fields[5].GetCppString(); - pGameEvent.state = (GameEventState)(fields[6].GetUInt8()); - pGameEvent.nextstart = 0; - - if(pGameEvent.length==0 && pGameEvent.state == GAMEEVENT_NORMAL) // length>0 is validity check - { - sLog.outErrorDb("`game_event` game event id (%i) isn't a world event and has length = 0, thus it can't be used.",event_id); - continue; - } + GameEventData& pGameEvent = mGameEvent[event_id]; + uint64 starttime = fields[1].GetUInt64(); + pGameEvent.start = time_t(starttime); + uint64 endtime = fields[2].GetUInt64(); + pGameEvent.end = time_t(endtime); + pGameEvent.occurence = fields[3].GetUInt32(); + pGameEvent.length = fields[4].GetUInt32(); + pGameEvent.description = fields[5].GetCppString(); + pGameEvent.state = (GameEventState)(fields[6].GetUInt8()); + pGameEvent.nextstart = 0; + + if(pGameEvent.length==0 && pGameEvent.state == GAMEEVENT_NORMAL) // length>0 is validity check + { + sLog.outErrorDb("`game_event` game event id (%i) isn't a world event and has length = 0, thus it can't be used.",event_id); + continue; + } - } while( result->NextRow() ); + } while( result->NextRow() ); + delete result; - sLog.outString(); - sLog.outString( ">> Loaded %u game events", count ); - delete result; + sLog.outString(); + sLog.outString( ">> Loaded %u game events", count ); + } // load game event saves // 0 1 2 @@ -346,8 +348,8 @@ void GameEvent::LoadFromDB() count = 0; if( !result ) { - barGoLink bar2(1); - bar2.step(); + barGoLink bar(1); + bar.step(); sLog.outString(); sLog.outString(">> Loaded %u creatures in game events", count ); @@ -355,12 +357,12 @@ void GameEvent::LoadFromDB() else { - barGoLink bar2( result->GetRowCount() ); + barGoLink bar( result->GetRowCount() ); do { Field *fields = result->Fetch(); - bar2.step(); + bar.step(); uint32 guid = fields[0].GetUInt32(); int16 event_id = fields[1].GetInt16(); @@ -378,9 +380,10 @@ void GameEvent::LoadFromDB() crelist.push_back(guid); } while( result->NextRow() ); + delete result; + sLog.outString(); sLog.outString( ">> Loaded %u creatures in game events", count ); - delete result; } mGameEventGameobjectGuids.resize(mGameEvent.size()*2-1); @@ -391,8 +394,8 @@ void GameEvent::LoadFromDB() count = 0; if( !result ) { - barGoLink bar3(1); - bar3.step(); + barGoLink bar(1); + bar.step(); sLog.outString(); sLog.outString(">> Loaded %u gameobjects in game events", count ); @@ -400,12 +403,12 @@ void GameEvent::LoadFromDB() else { - barGoLink bar3( result->GetRowCount() ); + barGoLink bar( result->GetRowCount() ); do { Field *fields = result->Fetch(); - bar3.step(); + bar.step(); uint32 guid = fields[0].GetUInt32(); int16 event_id = fields[1].GetInt16(); @@ -423,10 +426,10 @@ void GameEvent::LoadFromDB() golist.push_back(guid); } while( result->NextRow() ); + delete result; + sLog.outString(); sLog.outString( ">> Loaded %u gameobjects in game events", count ); - - delete result; } mGameEventModelEquip.resize(mGameEvent.size()); @@ -439,8 +442,8 @@ void GameEvent::LoadFromDB() count = 0; if( !result ) { - barGoLink bar3(1); - bar3.step(); + barGoLink bar(1); + bar.step(); sLog.outString(); sLog.outString(">> Loaded %u model/equipment changes in game events", count ); @@ -448,12 +451,12 @@ void GameEvent::LoadFromDB() else { - barGoLink bar3( result->GetRowCount() ); + barGoLink bar( result->GetRowCount() ); do { Field *fields = result->Fetch(); - bar3.step(); + bar.step(); uint32 guid = fields[0].GetUInt32(); uint16 event_id = fields[1].GetUInt16(); @@ -483,10 +486,10 @@ void GameEvent::LoadFromDB() equiplist.push_back(std::pair<uint32, ModelEquip>(guid, newModelEquipSet)); } while( result->NextRow() ); + delete result; + sLog.outString(); sLog.outString( ">> Loaded %u model/equipment changes in game events", count ); - - delete result; } mGameEventCreatureQuests.resize(mGameEvent.size()); @@ -496,8 +499,8 @@ void GameEvent::LoadFromDB() count = 0; if( !result ) { - barGoLink bar3(1); - bar3.step(); + barGoLink bar(1); + bar.step(); sLog.outString(); sLog.outString(">> Loaded %u quests additions in game events", count ); @@ -505,12 +508,12 @@ void GameEvent::LoadFromDB() else { - barGoLink bar3( result->GetRowCount() ); + barGoLink bar( result->GetRowCount() ); do { Field *fields = result->Fetch(); - bar3.step(); + bar.step(); uint32 id = fields[0].GetUInt32(); uint32 quest = fields[1].GetUInt32(); uint16 event_id = fields[2].GetUInt16(); @@ -569,10 +572,10 @@ void GameEvent::LoadFromDB() questlist.push_back(QuestRelation(id, quest)); } while( result->NextRow() ); + delete result; + sLog.outString(); sLog.outString( ">> Loaded %u quests additions in game events", count ); - - delete result; } // Load quest to (event,condition) mapping diff --git a/src/game/GameEvent.h b/src/game/GameEvent.h index 2655a5925db..ab5a1ed3292 100644 --- a/src/game/GameEvent.h +++ b/src/game/GameEvent.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index b7487568e62..f2bf5739334 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -46,7 +46,7 @@ GameObject::GameObject() : WorldObject() m_objectType |= TYPEMASK_GAMEOBJECT; m_objectTypeId = TYPEID_GAMEOBJECT; // 2.3.2 - 0x58 - m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION); m_valuesCount = GAMEOBJECT_END; m_respawnTime = 0; @@ -93,11 +93,12 @@ void GameObject::RemoveFromWorld() WorldObject::RemoveFromWorld(); } -bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state, uint32 ArtKit) +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, uint32 go_state, uint32 ArtKit) { Relocate(x,y,z,ang); SetMapId(map->GetId()); SetInstanceId(map->GetInstanceId()); + SetPhaseMask(phaseMask,false); if(!IsPositionValid()) { @@ -127,17 +128,33 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float SetFloatValue(GAMEOBJECT_POS_Z, z); SetFloatValue(GAMEOBJECT_FACING, ang); //this is not facing angle - SetFloatValue (GAMEOBJECT_ROTATION, rotation0); - SetFloatValue (GAMEOBJECT_ROTATION+1, rotation1); - SetFloatValue (GAMEOBJECT_ROTATION+2, rotation2); - SetFloatValue (GAMEOBJECT_ROTATION+3, rotation3); + int64 rotation = 0; + + float f_rot1 = sin(ang / 2.0f); + int64 i_rot1 = f_rot1 / atan(pow(2.0f, -20.0f)); + rotation |= (i_rot1 << 43 >> 43) & 0x00000000001FFFFF; + + //float f_rot2 = sin(0.0f / 2.0f); + //int64 i_rot2 = f_rot2 / atan(pow(2.0f, -20.0f)); + //rotation |= (((i_rot2 << 22) >> 32) >> 11) & 0x000003FFFFE00000; + + //float f_rot3 = sin(0.0f / 2.0f); + //int64 i_rot3 = f_rot3 / atan(pow(2.0f, -21.0f)); + //rotation |= (i_rot3 >> 42) & 0x7FFFFC0000000000; + + SetUInt64Value(GAMEOBJECT_ROTATION, rotation); + + SetFloatValue(GAMEOBJECT_PARENTROTATION+0, rotation0); + SetFloatValue(GAMEOBJECT_PARENTROTATION+1, rotation1); + SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2); + SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3); SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); - SetUInt32Value(OBJECT_FIELD_ENTRY, goinfo->id); + SetEntry(goinfo->id); SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); @@ -146,7 +163,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float SetGoAnimProgress(animprogress); - SetUInt32Value (GAMEOBJECT_ARTKIT, ArtKit); + SetByteValue(GAMEOBJECT_BYTES_1, 2, ArtKit); // Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22) if (goinfo->type == GAMEOBJECT_TYPE_SPELLCASTER) @@ -264,7 +281,7 @@ void GameObject::Update(uint32 /*p_time*/) return; } // respawn timer - MapManager::Instance().GetMap(GetMapId(), this)->Add(this); + GetMap()->Add(this); break; } } @@ -309,8 +326,8 @@ void GameObject::Update(uint32 /*p_time*/) // search unfriendly creature if(owner && NeedDespawn) // hunter trap { - Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius); - Trinity::UnitSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> checker(ok, u_check); + MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, owner, radius); + MaNGOS::UnitSearcher<MaNGOS::AnyUnfriendlyUnitInObjectRangeCheck> checker(this,ok, u_check); CellLock<GridReadGuard> cell_lock(cell, p); @@ -330,8 +347,8 @@ void GameObject::Update(uint32 /*p_time*/) // affect only players Player* p_ok = NULL; - Trinity::AnyPlayerInObjectRangeCheck p_check(this, radius); - Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck> checker(p_ok, p_check); + MaNGOS::AnyPlayerInObjectRangeCheck p_check(this, radius); + MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> checker(this,p_ok, p_check); CellLock<GridReadGuard> cell_lock(cell, p); @@ -344,8 +361,8 @@ void GameObject::Update(uint32 /*p_time*/) { //Unit *caster = owner ? owner : ok; - //caster->CastSpell(ok, goInfo->trap.spellId, true); CastSpell(ok, goInfo->trap.spellId); + //caster->CastSpell(ok, goInfo->trap.spellId, true, 0, 0, GetGUID()); m_cooldownTime = time(NULL) + 4; // 4 seconds if(NeedDespawn) @@ -395,7 +412,7 @@ void GameObject::Update(uint32 /*p_time*/) for (; it != end; it++) { Unit* owner = Unit::GetUnit(*this, uint64(*it)); - if (owner) owner->CastSpell(owner, spellId, false); + if (owner) owner->CastSpell(owner, spellId, false, 0, 0, GetGUID()); } m_unique_users.clear(); @@ -414,7 +431,7 @@ void GameObject::Update(uint32 /*p_time*/) //burning flags in some battlegrounds, if you find better condition, just add it if (GetGoAnimProgress() > 0) { - SendObjectDeSpawnAnim(this->GetGUID()); + SendObjectDeSpawnAnim(GetGUID()); //reset flags SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags); } @@ -451,7 +468,7 @@ void GameObject::Refresh() return; if(isSpawned()) - MapManager::Instance().GetMap(GetMapId(), this)->Add(this); + GetMap()->Add(this); } void GameObject::AddUniqueUse(Player* player) @@ -470,7 +487,7 @@ void GameObject::Delete() AddObjectToRemoveList(); } -void GameObject::getFishLoot(Loot *fishloot) +void GameObject::getFishLoot(Loot *fishloot, Player* loot_owner) { fishloot->clear(); @@ -478,10 +495,10 @@ void GameObject::getFishLoot(Loot *fishloot) // if subzone loot exist use it if(LootTemplates_Fishing.HaveLootFor(subzone)) - fishloot->FillLoot(subzone, LootTemplates_Fishing, NULL); + fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner,true); // else use zone loot else - fishloot->FillLoot(GetZoneId(), LootTemplates_Fishing, NULL); + fishloot->FillLoot(GetZoneId(), LootTemplates_Fishing, loot_owner,true); } void GameObject::SaveToDB() @@ -495,10 +512,10 @@ void GameObject::SaveToDB() return; } - SaveToDB(GetMapId(), data->spawnMask); + SaveToDB(GetMapId(), data->spawnMask, data->phaseMask); } -void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask) +void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) { const GameObjectInfo *goI = GetGOInfo(); @@ -513,38 +530,40 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask) // data->guid = guid don't must be update at save data.id = GetEntry(); data.mapid = mapid; + data.phaseMask = phaseMask; data.posX = GetFloatValue(GAMEOBJECT_POS_X); data.posY = GetFloatValue(GAMEOBJECT_POS_Y); data.posZ = GetFloatValue(GAMEOBJECT_POS_Z); data.orientation = GetFloatValue(GAMEOBJECT_FACING); - data.rotation0 = GetFloatValue(GAMEOBJECT_ROTATION+0); - data.rotation1 = GetFloatValue(GAMEOBJECT_ROTATION+1); - data.rotation2 = GetFloatValue(GAMEOBJECT_ROTATION+2); - data.rotation3 = GetFloatValue(GAMEOBJECT_ROTATION+3); + data.rotation0 = GetFloatValue(GAMEOBJECT_PARENTROTATION+0); + data.rotation1 = GetFloatValue(GAMEOBJECT_PARENTROTATION+1); + data.rotation2 = GetFloatValue(GAMEOBJECT_PARENTROTATION+2); + data.rotation3 = GetFloatValue(GAMEOBJECT_PARENTROTATION+3); data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime; data.animprogress = GetGoAnimProgress(); data.go_state = GetGoState(); data.spawnMask = spawnMask; - data.ArtKit = GetUInt32Value (GAMEOBJECT_ARTKIT); + data.ArtKit = GetGoArtKit(); // updated in DB std::ostringstream ss; ss << "INSERT INTO gameobject VALUES ( " << m_DBTableGuid << ", " - << GetUInt32Value (OBJECT_FIELD_ENTRY) << ", " + << GetEntry() << ", " << mapid << ", " << (uint32)spawnMask << ", " + << (uint32)GetPhaseMask() << "," << GetFloatValue(GAMEOBJECT_POS_X) << ", " << GetFloatValue(GAMEOBJECT_POS_Y) << ", " << GetFloatValue(GAMEOBJECT_POS_Z) << ", " << GetFloatValue(GAMEOBJECT_FACING) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION+1) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION+2) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION+3) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION+1) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION+2) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION+3) << ", " << m_respawnDelayTime << ", " - << GetGoAnimProgress() << ", " - << GetGoState() << ")"; + << (uint32)GetGoAnimProgress() << ", " + << (uint32)GetGoState() << ")"; WorldDatabase.BeginTransaction(); WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid); @@ -563,7 +582,8 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map) } uint32 entry = data->id; - uint32 map_id = data->mapid; + //uint32 map_id = data->mapid; // already used before call + uint32 phaseMask = data->phaseMask; float x = data->posX; float y = data->posY; float z = data->posZ; @@ -581,7 +601,7 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map) m_DBTableGuid = guid; if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); - if (!Create(guid,entry, map, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, ArtKit) ) + if (!Create(guid,entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, ArtKit) ) return false; switch(GetGOInfo()->type) @@ -724,10 +744,6 @@ bool GameObject::isVisibleForInState(Player const* u, bool inVisibleList) const if(owner && u->IsHostileTo(owner) && !canDetectTrap(u, GetDistance(u))) return false; } - - // Smuggled Mana Cell required 10 invisibility type detection/state - if(GetEntry()==187039 && ((u->m_detectInvisibilityMask | u->m_invisibilityMask) & (1<<10))==0) - return false; } // check distance @@ -820,8 +836,8 @@ void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target) Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; - Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*target,trapEntry,range); - Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(trapGO,go_check); + MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*target,trapEntry,range); + MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck> checker(this, trapGO,go_check); TypeContainerVisitor<Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker); CellLock<GridReadGuard> cell_lock(cell, p); @@ -831,7 +847,7 @@ void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target) // found correct GO // FIXME: when GO casting will be implemented trap must cast spell to target if(trapGO) - target->CastSpell(target,trapSpell,true); + target->CastSpell(target,trapSpell,true, 0, 0, GetGUID()); } GameObject* GameObject::LookupFishingHoleAround(float range) @@ -841,8 +857,8 @@ GameObject* GameObject::LookupFishingHoleAround(float range) CellPair p(Trinity::ComputeCellPair(GetPositionX(),GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; - Trinity::NearestGameObjectFishingHole u_check(*this, range); - Trinity::GameObjectSearcher<Trinity::NearestGameObjectFishingHole> checker(ok, u_check); + MaNGOS::NearestGameObjectFishingHole u_check(*this, range); + MaNGOS::GameObjectSearcher<MaNGOS::NearestGameObjectFishingHole> checker(this, ok, u_check); CellLock<GridReadGuard> cell_lock(cell, p); @@ -867,9 +883,9 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore) } -void GameObject::SetGoArtKit(uint32 kit) +void GameObject::SetGoArtKit(uint8 kit) { - SetUInt32Value(GAMEOBJECT_ARTKIT, kit); + SetByteValue(GAMEOBJECT_BYTES_1, 2, kit); GameObjectData *data = const_cast<GameObjectData*>(objmgr.GetGOData(m_DBTableGuid)); if(data) data->ArtKit = kit; @@ -974,7 +990,7 @@ void GameObject::Use(Unit* user) // fallback, will always work player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET); } - player->SetStandState(PLAYER_STATE_SIT_LOW_CHAIR+info->chair.height); + player->SetStandState(UNIT_STAND_STATE_SIT_LOW_CHAIR+info->chair.height); return; } //big gun, its a spell/aura @@ -1268,6 +1284,26 @@ void GameObject::Use(Unit* user) } break; } + case GAMEOBJECT_TYPE_BARBER_CHAIR: //32 + { + GameObjectInfo const* info = GetGOInfo(); + if(!info) + return; + + if(user->GetTypeId()!=TYPEID_PLAYER) + return; + + Player* player = (Player*)user; + + // fallback, will always work + player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET); + + WorldPacket data(SMSG_ENABLE_BARBER_SHOP, 0); + player->GetSession()->SendPacket(&data); + + player->SetStandState(UNIT_STAND_STATE_SIT_LOW_CHAIR+info->barberChair.chairheight); + return; + } default: sLog.outDebug("Unknown Object Type %u", GetGoType()); break; diff --git a/src/game/GameObject.h b/src/game/GameObject.h index 3b837a0550c..a492e4dad35 100644 --- a/src/game/GameObject.h +++ b/src/game/GameObject.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -336,12 +336,12 @@ struct GameObjectInfo uint32 mapID; //0 uint32 difficulty; //1 } dungeonDifficulty; - //32 GAMEOBJECT_TYPE_DO_NOT_USE_YET + //32 GAMEOBJECT_TYPE_BARBER_CHAIR struct { - uint32 mapID; //0 - uint32 difficulty; //1 - } doNotUseYet; + uint32 chairheight; //0 + uint32 heightOffset; //1 + } barberChair; //33 GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING struct { @@ -350,6 +350,13 @@ struct GameObjectInfo uint32 state1Name; //2 uint32 state2Name; //3 } destructibleBuilding; + //34 GAMEOBJECT_TYPE_TRAPDOOR + struct + { + uint32 whenToPause; // 0 + uint32 startOpen; // 1 + uint32 autoClose; // 2 + } trapDoor; // not use for specific field access (only for output with loop by all filed), also this determinate max union size struct // GAMEOBJECT_TYPE_SPELLCASTER @@ -370,7 +377,8 @@ struct GameObjectLocale struct GameObjectData { uint32 id; // entry in gamobject_template - uint32 mapid; + uint16 mapid; + uint16 phaseMask; float posX; float posY; float posZ; @@ -419,7 +427,7 @@ class TRINITY_DLL_SPEC GameObject : public WorldObject void AddToWorld(); void RemoveFromWorld(); - bool Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state, uint32 ArtKit = 0); + bool 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, uint32 go_state, uint32 ArtKit = 0); void Update(uint32 p_time); static GameObject* GetGameObject(WorldObject& object, uint64 guid); GameObjectInfo const* GetGOInfo() const; @@ -449,7 +457,7 @@ class TRINITY_DLL_SPEC GameObject : public WorldObject const char* GetNameForLocaleIdx(int32 locale_idx) const; void SaveToDB(); - void SaveToDB(uint32 mapid, uint8 spawnMask); + void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask); bool LoadFromDB(uint32 guid, Map *map); void DeleteFromDB(); void SetLootState(LootState s) { m_lootState = s; } @@ -503,15 +511,15 @@ class TRINITY_DLL_SPEC GameObject : public WorldObject void Delete(); void SetSpellId(uint32 id) { m_spellId = id;} uint32 GetSpellId() const { return m_spellId;} - void getFishLoot(Loot *loot); - GameobjectTypes GetGoType() const { return GameobjectTypes(GetUInt32Value(GAMEOBJECT_TYPE_ID)); } - void SetGoType(GameobjectTypes type) { SetUInt32Value(GAMEOBJECT_TYPE_ID, type); } - uint32 GetGoState() const { return GetUInt32Value(GAMEOBJECT_STATE); } - void SetGoState(uint32 state) { SetUInt32Value(GAMEOBJECT_STATE, state); } - uint32 GetGoArtKit() const { return GetUInt32Value(GAMEOBJECT_ARTKIT); } - void SetGoArtKit(uint32 artkit); - uint32 GetGoAnimProgress() const { return GetUInt32Value(GAMEOBJECT_ANIMPROGRESS); } - void SetGoAnimProgress(uint32 animprogress) { SetUInt32Value(GAMEOBJECT_ANIMPROGRESS, animprogress); } + void getFishLoot(Loot *loot, Player* loot_owner); + GameobjectTypes GetGoType() const { return GameobjectTypes(GetByteValue(GAMEOBJECT_BYTES_1, 1)); } + void SetGoType(GameobjectTypes type) { SetByteValue(GAMEOBJECT_BYTES_1, 1, type); } + uint8 GetGoState() const { return GetByteValue(GAMEOBJECT_BYTES_1, 0); } + void SetGoState(uint8 state) { SetByteValue(GAMEOBJECT_BYTES_1, 0, state); } + uint8 GetGoArtKit() const { return GetByteValue(GAMEOBJECT_BYTES_1, 2); } + void SetGoArtKit(uint8 artkit); + uint8 GetGoAnimProgress() const { return GetByteValue(GAMEOBJECT_BYTES_1, 3); } + void SetGoAnimProgress(uint8 animprogress) { SetByteValue(GAMEOBJECT_BYTES_1, 3, animprogress); } void Use(Unit* user); diff --git a/src/game/GlobalEvents.cpp b/src/game/GlobalEvents.cpp index 635d426f694..807b0c695d0 100644 --- a/src/game/GlobalEvents.cpp +++ b/src/game/GlobalEvents.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -55,7 +55,7 @@ static void CorpsesEraseCallBack(QueryResult *result, bool bones) { if(!ObjectAccessor::Instance().ConvertCorpseForPlayer(player_guid)) { - sLog.outDebug("Corpse %u not found in world. Delete from DB.",guidlow); + sLog.outDebug("Corpse %u not found in world or bones creating forbidden. Delete from DB.",guidlow); CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow); } } diff --git a/src/game/GlobalEvents.h b/src/game/GlobalEvents.h index a1c6b31a406..0b76b09330a 100644 --- a/src/game/GlobalEvents.h +++ b/src/game/GlobalEvents.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index 85414fa3372..f8b1ac04f99 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -127,7 +127,7 @@ bool PlayerMenu::GossipOptionCoded( unsigned int Selection ) void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ) { WorldPacket data( SMSG_GOSSIP_MESSAGE, (100) ); // guess size - data << npcGUID; + data << uint64(npcGUID); data << uint32(0); // new 2.4.0 data << uint32( TitleTextId ); data << uint32( mGossipMenu.MenuItemCount() ); // max count 0x0F @@ -417,10 +417,14 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID } data << uint64(npcGUID); + data << uint64(0); // wotlk, something todo with quest sharing? data << uint32(pQuest->GetQuestId()); - data << Title << Details << Objectives; + data << Title; + data << Details; + data << Objectives; data << uint32(ActivateAccept); data << uint32(pQuest->GetSuggestedPlayers()); + data << uint8(0); // new wotlk if (pQuest->HasFlag(QUEST_FLAGS_HIDDEN_REWARDS)) { @@ -466,6 +470,7 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0) data << uint32(pQuest->GetRewSpellCast()); // casted spell data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) + data << uint32(pQuest->GetBonusTalents()); // bonus talents data << uint32(QUEST_EMOTE_COUNT); for (uint32 i=0; i < QUEST_EMOTE_COUNT; i++) @@ -542,6 +547,8 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest ) data << uint32(pQuest->GetSrcItemId()); data << uint32(pQuest->GetFlags() & 0xFFFF); data << uint32(pQuest->GetCharTitleId()); // CharTitleId, new 2.4.0, player gets this title (id from CharTitles) + data << uint32(pQuest->GetPlayersSlain()); // players slain + data << uint32(pQuest->GetBonusTalents()); // bonus talents int iI; @@ -588,15 +595,23 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest ) data << uint32(pQuest->ReqCreatureOrGOId[iI]); } data << uint32(pQuest->ReqCreatureOrGOCount[iI]); + data << uint32(0); // added in WotLK, dunno if offset if correct + } + + for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; ++iI) + { data << uint32(pQuest->ReqItemId[iI]); data << uint32(pQuest->ReqItemCount[iI]); } + data << uint32(0); // TODO: 5 item objective + data << uint32(0); + for (iI = 0; iI < QUEST_OBJECTIVES_COUNT; iI++) data << ObjectiveText[iI]; pSession->SendPacket( &data ); - sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u",pQuest->GetQuestId() ); + sLog.outDebug( "WORLD: Sent SMSG_QUEST_QUERY_RESPONSE questid=%u", pQuest->GetQuestId() ); } void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID, bool EnbleNext ) @@ -678,9 +693,10 @@ void PlayerMenu::SendQuestGiverOfferReward( Quest const* pQuest, uint64 npcGUID, data << uint32(0x08); // unused by client? data << uint32(pQuest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast==0) data << uint32(pQuest->GetRewSpellCast()); // casted spell - data << uint32(0x00); // unk, NOT honor + data << uint32(0); // unknown + data << uint32(pQuest->GetBonusTalents()); // bonus talents pSession->SendPacket( &data ); - sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() ); + sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), pQuest->GetQuestId() ); } void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID, bool Completable, bool CloseOnCancel ) diff --git a/src/game/GossipDef.h b/src/game/GossipDef.h index ac4ac213b3d..cb93a4e7a91 100644 --- a/src/game/GossipDef.h +++ b/src/game/GossipDef.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/GridDefines.h b/src/game/GridDefines.h index 1c67bd0ca3a..58871f68c03 100644 --- a/src/game/GridDefines.h +++ b/src/game/GridDefines.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp index a189aa72304..638de03fe45 100644 --- a/src/game/GridNotifiers.cpp +++ b/src/game/GridNotifiers.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -146,7 +146,7 @@ VisibleNotifier::Notify() // send data at target visibility change (adding to client) for(std::set<WorldObject*>::const_iterator vItr = i_visibleNow.begin(); vItr != i_visibleNow.end(); ++vItr) if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT)) - i_player.SendAuraDurationsForTarget((Unit*)(*vItr)); + i_player.SendAurasForTarget((Unit*)(*vItr)); } void @@ -154,6 +154,11 @@ Deliverer::Visit(PlayerMapType &m) { for (PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) { + //if (!i_source.InSamePhase(iter->getSource())) + // continue; + if(!iter->getSource()->InSamePhase(i_phaseMask)) + continue; + if (!i_dist || iter->getSource()->GetDistance(&i_source) <= i_dist) { // Send packet to all who are sharing the player's vision @@ -174,6 +179,9 @@ Deliverer::Visit(CreatureMapType &m) { for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) { + if(!iter->getSource()->InSamePhase(i_phaseMask)) + continue; + if (!i_dist || iter->getSource()->GetDistance(&i_source) <= i_dist) { // Send packet to all who are sharing the creature's vision @@ -192,6 +200,9 @@ Deliverer::Visit(DynamicObjectMapType &m) { for (DynamicObjectMapType::iterator iter = m.begin(); iter != m.end(); ++iter) { + if(!iter->getSource()->InSamePhase(i_phaseMask)) + continue; + if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) { // Send packet back to the caster if the caster has vision of dynamic object @@ -249,9 +260,6 @@ ObjectUpdater::Visit(GridRefManager<T> &m) } } -template void ObjectUpdater::Visit<GameObject>(GameObjectMapType &); -template void ObjectUpdater::Visit<DynamicObject>(DynamicObjectMapType &); - bool CannibalizeObjectCheck::operator()(Corpse* u) { // ignore bones @@ -268,3 +276,6 @@ bool CannibalizeObjectCheck::operator()(Corpse* u) return false; } + +template void ObjectUpdater::Visit<GameObject>(GameObjectMapType &); +template void ObjectUpdater::Visit<DynamicObject>(DynamicObjectMapType &); diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h index 4bbb31c65c0..740ded8e17e 100644 --- a/src/game/GridNotifiers.h +++ b/src/game/GridNotifiers.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -96,8 +96,10 @@ namespace Trinity std::set<uint64> plr_list; bool i_toPossessor; bool i_toSelf; + uint32 i_phaseMask; float i_dist; - Deliverer(WorldObject &src, WorldPacket *msg, bool to_possessor, bool to_self, float dist = 0.0f) : i_source(src), i_message(msg), i_toPossessor(to_possessor), i_toSelf(to_self), i_dist(dist) {} + Deliverer(WorldObject &src, WorldPacket *msg, bool to_possessor, bool to_self, float dist = 0.0f) + : i_source(src), i_message(msg), i_toPossessor(to_possessor), i_toSelf(to_self), i_dist(dist), i_phaseMask(src.GetPhaseMask()) {} void Visit(PlayerMapType &m); void Visit(CreatureMapType &m); void Visit(DynamicObjectMapType &m); @@ -215,10 +217,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL WorldObjectSearcher { + uint32 i_phaseMask; WorldObject* &i_object; Check &i_check; - WorldObjectSearcher(WorldObject* & result, Check& check) : i_object(result),i_check(check) {} + WorldObjectSearcher(WorldObject const* searcher, WorldObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} void Visit(GameObjectMapType &m); void Visit(PlayerMapType &m); @@ -232,10 +236,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL WorldObjectListSearcher { + uint32 i_phaseMask; std::list<WorldObject*> &i_objects; Check& i_check; - WorldObjectListSearcher(std::list<WorldObject*> &objects, Check & check) : i_objects(objects),i_check(check) {} + WorldObjectListSearcher(WorldObject const* searcher, std::list<WorldObject*> &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} void Visit(PlayerMapType &m); void Visit(CreatureMapType &m); @@ -249,37 +255,44 @@ namespace Trinity template<class Do> struct TRINITY_DLL_DECL WorldObjectWorker { + uint32 i_phaseMask; Do const& i_do; - explicit WorldObjectWorker(Do const& _do) : i_do(_do) {} + WorldObjectWorker(WorldObject const* searcher, Do const& _do) + : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} void Visit(GameObjectMapType &m) { for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - i_do(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); } void Visit(PlayerMapType &m) { for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - i_do(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); } void Visit(CreatureMapType &m) { for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - i_do(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); } void Visit(CorpseMapType &m) { for(CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - i_do(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); } void Visit(DynamicObjectMapType &m) { for(DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - i_do(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); } template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {} @@ -290,10 +303,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL GameObjectSearcher { + uint32 i_phaseMask; GameObject* &i_object; Check &i_check; - GameObjectSearcher(GameObject* & result, Check& check) : i_object(result),i_check(check) {} + GameObjectSearcher(WorldObject const* searcher, GameObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} void Visit(GameObjectMapType &m); @@ -304,10 +319,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL GameObjectLastSearcher { + uint32 i_phaseMask; GameObject* &i_object; Check& i_check; - GameObjectLastSearcher(GameObject* & result, Check& check) : i_object(result),i_check(check) {} + GameObjectLastSearcher(WorldObject const* searcher, GameObject* & result, Check& check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result), i_check(check) {} void Visit(GameObjectMapType &m); @@ -317,10 +334,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL GameObjectListSearcher { + uint32 i_phaseMask; std::list<GameObject*> &i_objects; Check& i_check; - GameObjectListSearcher(std::list<GameObject*> &objects, Check & check) : i_objects(objects),i_check(check) {} + GameObjectListSearcher(WorldObject const* searcher, std::list<GameObject*> &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects), i_check(check) {} void Visit(GameObjectMapType &m); @@ -333,10 +352,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL UnitSearcher { + uint32 i_phaseMask; Unit* &i_object; Check & i_check; - UnitSearcher(Unit* & result, Check & check) : i_object(result),i_check(check) {} + UnitSearcher(WorldObject const* searcher, Unit* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} void Visit(CreatureMapType &m); void Visit(PlayerMapType &m); @@ -348,10 +369,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL UnitLastSearcher { + uint32 i_phaseMask; Unit* &i_object; Check & i_check; - UnitLastSearcher(Unit* & result, Check & check) : i_object(result),i_check(check) {} + UnitLastSearcher(WorldObject const* searcher, Unit* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} void Visit(CreatureMapType &m); void Visit(PlayerMapType &m); @@ -363,10 +386,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL UnitListSearcher { + uint32 i_phaseMask; std::list<Unit*> &i_objects; Check& i_check; - UnitListSearcher(std::list<Unit*> &objects, Check & check) : i_objects(objects),i_check(check) {} + UnitListSearcher(WorldObject const* searcher, std::list<Unit*> &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} void Visit(PlayerMapType &m); void Visit(CreatureMapType &m); @@ -379,10 +404,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL CreatureSearcher { + uint32 i_phaseMask; Creature* &i_object; Check & i_check; - CreatureSearcher(Creature* & result, Check & check) : i_object(result),i_check(check) {} + CreatureSearcher(WorldObject const* searcher, Creature* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} void Visit(CreatureMapType &m); @@ -393,10 +420,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL CreatureLastSearcher { + uint32 i_phaseMask; Creature* &i_object; Check & i_check; - CreatureLastSearcher(Creature* & result, Check & check) : i_object(result),i_check(check) {} + CreatureLastSearcher(WorldObject const* searcher, Creature* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} void Visit(CreatureMapType &m); @@ -406,10 +435,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL CreatureListSearcher { + uint32 i_phaseMask; std::list<Creature*> &i_objects; Check& i_check; - CreatureListSearcher(std::list<Creature*> &objects, Check & check) : i_objects(objects),i_check(check) {} + CreatureListSearcher(WorldObject const* searcher, std::list<Creature*> &objects, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_objects(objects),i_check(check) {} void Visit(CreatureMapType &m); @@ -421,10 +452,12 @@ namespace Trinity template<class Check> struct TRINITY_DLL_DECL PlayerSearcher { + uint32 i_phaseMask; Player* &i_object; Check & i_check; - PlayerSearcher(Player* & result, Check & check) : i_object(result),i_check(check) {} + PlayerSearcher(WorldObject const* searcher, Player* & result, Check & check) + : i_phaseMask(searcher->GetPhaseMask()), i_object(result),i_check(check) {} void Visit(PlayerMapType &m); @@ -434,14 +467,17 @@ namespace Trinity template<class Do> struct TRINITY_DLL_DECL PlayerWorker { + uint32 i_phaseMask; Do& i_do; - explicit PlayerWorker(Do& _do) : i_do(_do) {} + PlayerWorker(WorldObject const* searcher, Do& _do) + : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {} void Visit(PlayerMapType &m) { for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - i_do(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + i_do(itr->getSource()); } template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {} diff --git a/src/game/GridNotifiersImpl.h b/src/game/GridNotifiersImpl.h index dfb202a37e1..c237c95a28b 100644 --- a/src/game/GridNotifiersImpl.h +++ b/src/game/GridNotifiersImpl.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -155,7 +155,7 @@ inline void Trinity::DynamicObjectUpdater::VisitHelper(Unit* target) if( target->GetTypeId()==TYPEID_PLAYER && target != i_check && (((Player*)target)->isGameMaster() || ((Player*)target)->GetVisibility()==VISIBILITY_OFF) ) return; - if( i_check->GetTypeId()==TYPEID_PLAYER ) + if (i_check->GetTypeId()==TYPEID_PLAYER ) { if (i_check->IsFriendlyTo( target )) return; @@ -172,7 +172,7 @@ inline void Trinity::DynamicObjectUpdater::VisitHelper(Unit* target) SpellEntry const *spellInfo = sSpellStore.LookupEntry(i_dynobject.GetSpellId()); uint32 eff_index = i_dynobject.GetEffIndex(); // Check target immune to spell or aura - if (target->IsImmunedToSpell(spellInfo) || target->IsImmunedToSpellEffect(spellInfo->Effect[eff_index], spellInfo->EffectMechanic[eff_index])) + if (target->IsImmunedToSpell(spellInfo) || target->IsImmunedToSpellEffect(spellInfo, eff_index)) return; // Apply PersistentAreaAura on target PersistentAreaAura* Aur = new PersistentAreaAura(spellInfo, eff_index, NULL, target, i_dynobject.GetCaster()); @@ -209,7 +209,10 @@ void Trinity::WorldObjectSearcher<Check>::Visit(GameObjectMapType &m) for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { - if(i_check(itr->getSource())) + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + + if (i_check(itr->getSource())) { i_object = itr->getSource(); return; @@ -226,6 +229,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(PlayerMapType &m) for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) { i_object = itr->getSource(); @@ -243,6 +249,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CreatureMapType &m) for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) { i_object = itr->getSource(); @@ -260,6 +269,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(CorpseMapType &m) for(CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) { i_object = itr->getSource(); @@ -277,6 +289,9 @@ void Trinity::WorldObjectSearcher<Check>::Visit(DynamicObjectMapType &m) for(DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) { i_object = itr->getSource(); @@ -289,40 +304,45 @@ template<class Check> void Trinity::WorldObjectListSearcher<Check>::Visit(PlayerMapType &m) { for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if(i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); } template<class Check> void Trinity::WorldObjectListSearcher<Check>::Visit(CreatureMapType &m) { for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if(i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); } template<class Check> void Trinity::WorldObjectListSearcher<Check>::Visit(CorpseMapType &m) { for(CorpseMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if(i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); } template<class Check> void Trinity::WorldObjectListSearcher<Check>::Visit(GameObjectMapType &m) { for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if(i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); } template<class Check> void Trinity::WorldObjectListSearcher<Check>::Visit(DynamicObjectMapType &m) { for(DynamicObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if(i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); } // Gameobject searchers @@ -336,6 +356,9 @@ void Trinity::GameObjectSearcher<Check>::Visit(GameObjectMapType &m) for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) { i_object = itr->getSource(); @@ -349,6 +372,9 @@ void Trinity::GameObjectLastSearcher<Check>::Visit(GameObjectMapType &m) { for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) i_object = itr->getSource(); } @@ -358,8 +384,9 @@ template<class Check> void Trinity::GameObjectListSearcher<Check>::Visit(GameObjectMapType &m) { for(GameObjectMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if(i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); } // Unit searchers @@ -373,6 +400,9 @@ void Trinity::UnitSearcher<Check>::Visit(CreatureMapType &m) for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) { i_object = itr->getSource(); @@ -390,6 +420,9 @@ void Trinity::UnitSearcher<Check>::Visit(PlayerMapType &m) for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) { i_object = itr->getSource(); @@ -403,6 +436,9 @@ void Trinity::UnitLastSearcher<Check>::Visit(CreatureMapType &m) { for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) i_object = itr->getSource(); } @@ -413,6 +449,9 @@ void Trinity::UnitLastSearcher<Check>::Visit(PlayerMapType &m) { for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) i_object = itr->getSource(); } @@ -422,16 +461,18 @@ template<class Check> void Trinity::UnitListSearcher<Check>::Visit(PlayerMapType &m) { for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if(i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); } template<class Check> void Trinity::UnitListSearcher<Check>::Visit(CreatureMapType &m) { for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if(i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + if(i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); } // Creature searchers @@ -445,6 +486,9 @@ void Trinity::CreatureSearcher<Check>::Visit(CreatureMapType &m) for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) { i_object = itr->getSource(); @@ -458,6 +502,9 @@ void Trinity::CreatureLastSearcher<Check>::Visit(CreatureMapType &m) { for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) i_object = itr->getSource(); } @@ -467,8 +514,9 @@ template<class Check> void Trinity::CreatureListSearcher<Check>::Visit(CreatureMapType &m) { for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr) - if(i_check(itr->getSource())) - i_objects.push_back(itr->getSource()); + if(itr->getSource()->InSamePhase(i_phaseMask)) + if( i_check(itr->getSource())) + i_objects.push_back(itr->getSource()); } template<class Check> @@ -480,6 +528,9 @@ void Trinity::PlayerSearcher<Check>::Visit(PlayerMapType &m) for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) { + if(!itr->getSource()->InSamePhase(i_phaseMask)) + continue; + if(i_check(itr->getSource())) { i_object = itr->getSource(); diff --git a/src/game/GridStates.cpp b/src/game/GridStates.cpp index 5cf5c8b8c11..92df04ef06e 100644 --- a/src/game/GridStates.cpp +++ b/src/game/GridStates.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/GridStates.h b/src/game/GridStates.h index 2764d09506c..dd22c482c0a 100644 --- a/src/game/GridStates.h +++ b/src/game/GridStates.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Group.cpp b/src/game/Group.cpp index 829538f8af7..82778346837 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,12 +10,12 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Common.h" @@ -74,6 +74,8 @@ Group::~Group() for(uint8 i = 0; i < TOTAL_DIFFICULTIES; i++) for(BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr) itr->second.save->RemoveGroup(this); + + // Sub group counters clean up if (m_subGroupsCounts) delete[] m_subGroupsCounts; } @@ -203,6 +205,11 @@ void Group::ConvertToRaid() if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid)); SendUpdate(); + + // update quest related GO states (quest activity dependent from raid membership) + for(member_citerator citr = m_memberSlots.begin(); citr != m_memberSlots.end(); ++citr) + if(Player* player = objmgr.GetPlayer(citr->guid)) + player->UpdateForQuestsGO(); } bool Group::AddInvite(Player *player) @@ -288,6 +295,10 @@ bool Group::AddMember(const uint64 &guid, const char* name) } player->SetGroupUpdateFlag(GROUP_UPDATE_FULL); UpdatePlayerOutOfRange(player); + + // quest related GO state dependent from raid memebership + if(isRaidGroup()) + player->UpdateForQuestsGO(); } return true; @@ -302,9 +313,12 @@ uint32 Group::RemoveMember(const uint64 &guid, const uint8 &method) { bool leaderChanged = _removeMember(guid); - Player *player = objmgr.GetPlayer( guid ); // FG: TODO: could be removed, its just here for consistency - if (player) + if(Player *player = objmgr.GetPlayer( guid )) { + // quest related GO state dependent from raid membership + if(isRaidGroup()) + player->UpdateForQuestsGO(); + WorldPacket data; if(method == 1) @@ -363,6 +377,11 @@ void Group::Disband(bool hideDestroy) player->SetGroup(NULL); + // quest related GO state dependent from raid membership + if(isRaidGroup()) + player->UpdateForQuestsGO(); + + if(!player->GetSession()) continue; @@ -729,6 +748,8 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers) if(player && player->GetSession()) { + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT, roll->itemid, maxresul); + ItemPosCountVec dest; LootItem *item = &(roll->getLoot()->items[roll->itemSlot]); uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count ); @@ -774,6 +795,8 @@ void Group::CountTheRoll(Rolls::iterator rollI, uint32 NumberOfPlayers) if(player && player->GetSession()) { + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT, roll->itemid, maxresul); + ItemPosCountVec dest; LootItem *item = &(roll->getLoot()->items[roll->itemSlot]); uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count ); @@ -835,13 +858,10 @@ void Group::GetDataForXPAtKill(Unit const* victim, uint32& count,uint32& sum_lev ++count; sum_level += member->getLevel(); - // store maximum member level if(!member_with_max_level || member_with_max_level->getLevel() < member->getLevel()) member_with_max_level = member; - uint32 gray_level = Trinity::XP::GetGrayLevel(member->getLevel()); - // if the victim is higher level than the gray level of the currently examined group member, - // then set not_gray_member_with_max_level if needed. + uint32 gray_level = MaNGOS::XP::GetGrayLevel(member->getLevel()); if( victim->getLevel() > gray_level && (!not_gray_member_with_max_level || not_gray_member_with_max_level->getLevel() < member->getLevel())) not_gray_member_with_max_level = member; @@ -905,7 +925,6 @@ void Group::SendUpdate() data << (uint64)m_looterGuid; // looter guid data << (uint8)m_lootThreshold; // loot threshold data << (uint8)m_difficulty; // Heroic Mod Group - } player->GetSession()->SendPacket( &data ); } @@ -984,7 +1003,7 @@ bool Group::_addMember(const uint64 &guid, const char* name, bool isAssistant) } // We are raid group and no one slot is free if (!groupFound) - return false; + return false; } return _addMember(guid, name, isAssistant, groupid); @@ -1048,6 +1067,7 @@ bool Group::_removeMember(const uint64 &guid) if (slot != m_memberSlots.end()) { SubGroupCounterDecrease(slot->group); + m_memberSlots.erase(slot); } @@ -1207,6 +1227,7 @@ void Group::ChangeMembersGroup(const uint64 &guid, const uint8 &group) if(!isRaidGroup()) return; Player *player = objmgr.GetPlayer(guid); + if (!player) { uint8 prevSubGroup; @@ -1218,6 +1239,7 @@ void Group::ChangeMembersGroup(const uint64 &guid, const uint8 &group) SendUpdate(); } else + // This methods handles itself groupcounter decrease ChangeMembersGroup(player, group); } @@ -1311,7 +1333,7 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed ) SendUpdate(); } -uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot) +uint32 Group::CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot) { // check for min / max count uint32 memberscount = GetMembersCount(); @@ -1366,7 +1388,7 @@ uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint void Roll::targetObjectBuildLink() { // called from link() - this->getTarget()->addLootValidatorRef(this); + getTarget()->addLootValidatorRef(this); } void Group::SetDifficulty(uint8 difficulty) @@ -1474,7 +1496,7 @@ InstanceGroupBind* Group::BindToInstance(InstanceSave *save, bool permanent, boo InstanceGroupBind& bind = m_boundInstances[save->GetDifficulty()][save->GetMapId()]; if(bind.save) { - // when a boss is killed or when copying the player's binds to the group + // when a boss is killed or when copying the players's binds to the group if(permanent != bind.perm || save != bind.save) if(!load) CharacterDatabase.PExecute("UPDATE group_instance SET instance = '%u', permanent = '%u' WHERE leaderGuid = '%u' AND instance = '%u'", save->GetInstanceId(), permanent, GUID_LOPART(GetLeaderGUID()), bind.save->GetInstanceId()); } @@ -1535,4 +1557,4 @@ void Group::BroadcastGroupUpdate(void) DEBUG_LOG("-- Forced group value update for '%s'", pp->GetName()); } } -}
\ No newline at end of file +} diff --git a/src/game/Group.h b/src/game/Group.h index 9882966e3f6..f3af8deaf7d 100644 --- a/src/game/Group.h +++ b/src/game/Group.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -66,24 +66,25 @@ enum GroupUpdateFlags { GROUP_UPDATE_FLAG_NONE = 0x00000000, // nothing GROUP_UPDATE_FLAG_STATUS = 0x00000001, // uint16, flags - GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint16 - GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint16 + GROUP_UPDATE_FLAG_CUR_HP = 0x00000002, // uint32 + GROUP_UPDATE_FLAG_MAX_HP = 0x00000004, // uint32 GROUP_UPDATE_FLAG_POWER_TYPE = 0x00000008, // uint8 GROUP_UPDATE_FLAG_CUR_POWER = 0x00000010, // uint16 GROUP_UPDATE_FLAG_MAX_POWER = 0x00000020, // uint16 GROUP_UPDATE_FLAG_LEVEL = 0x00000040, // uint16 GROUP_UPDATE_FLAG_ZONE = 0x00000080, // uint16 GROUP_UPDATE_FLAG_POSITION = 0x00000100, // uint16, uint16 - GROUP_UPDATE_FLAG_AURAS = 0x00000200, // uint64 mask, for each bit set uint16 spellid + uint8 unk + GROUP_UPDATE_FLAG_AURAS = 0x00000200, // uint64 mask, for each bit set uint32 spellid + uint8 unk GROUP_UPDATE_FLAG_PET_GUID = 0x00000400, // uint64 pet guid GROUP_UPDATE_FLAG_PET_NAME = 0x00000800, // pet name, NULL terminated string GROUP_UPDATE_FLAG_PET_MODEL_ID = 0x00001000, // uint16, model id - GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00002000, // uint16 pet cur health - GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00004000, // uint16 pet max health + GROUP_UPDATE_FLAG_PET_CUR_HP = 0x00002000, // uint32 pet cur health + GROUP_UPDATE_FLAG_PET_MAX_HP = 0x00004000, // uint32 pet max health GROUP_UPDATE_FLAG_PET_POWER_TYPE = 0x00008000, // uint8 pet power type GROUP_UPDATE_FLAG_PET_CUR_POWER = 0x00010000, // uint16 pet cur power GROUP_UPDATE_FLAG_PET_MAX_POWER = 0x00020000, // uint16 pet max power - GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint16 spellid + uint8 unk, pet auras... + GROUP_UPDATE_FLAG_PET_AURAS = 0x00040000, // uint64 mask, for each bit set uint32 spellid + uint8 unk, pet auras... + GROUP_UPDATE_FLAG_VEHICLE_SEAT = 0x00080000, // uint32 vehicle_seat_id (index from VehicleSeat.dbc) GROUP_UPDATE_PET = 0x0007FC00, // all pet flags GROUP_UPDATE_FULL = 0x0007FFFF, // all known flags }; @@ -249,7 +250,7 @@ class TRINITY_DLL_SPEC Group void ConvertToRaid(); void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; } - uint32 CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot); + uint32 CanJoinBattleGroundQueue(BattleGroundTypeId bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot); void ChangeMembersGroup(const uint64 &guid, const uint8 &group); void ChangeMembersGroup(Player *player, const uint8 &group); diff --git a/src/game/GroupHandler.cpp b/src/game/GroupHandler.cpp index f875e833c77..574ebd7de75 100644 --- a/src/game/GroupHandler.cpp +++ b/src/game/GroupHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -162,6 +162,7 @@ void WorldSession::HandleGroupInviteOpcode( WorldPacket & recv_data ) // ok, we do it WorldPacket data(SMSG_GROUP_INVITE, 10); // guess size + data << uint8(1); // ok data << GetPlayer()->GetName(); player->GetSession()->SendPacket(&data); @@ -554,8 +555,17 @@ void WorldSession::HandleGroupChangeSubGroupOpcode( WorldPacket & recv_data ) return; /********************/ + //Do not allow leader to change group of player in combat + Player *movedPlayer=objmgr.GetPlayer(name.c_str()); + if (movedPlayer->isInCombat()) + { + WorldPacket data(SMSG_GROUP_SWAP_FAILED, (0)); + SendPacket(&data); + return; + } + // everything's fine, do it - group->ChangeMembersGroup(objmgr.GetPlayer(name.c_str()), groupNr); + group->ChangeMembersGroup(movedPlayer, groupNr); } void WorldSession::HandleGroupAssistantOpcode( WorldPacket & recv_data ) @@ -690,10 +700,10 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke } if (mask & GROUP_UPDATE_FLAG_CUR_HP) - *data << (uint16) player->GetHealth(); + *data << (uint32) player->GetHealth(); if (mask & GROUP_UPDATE_FLAG_MAX_HP) - *data << (uint16) player->GetMaxHealth(); + *data << (uint32) player->GetMaxHealth(); Powers powerType = player->getPowerType(); if (mask & GROUP_UPDATE_FLAG_POWER_TYPE) @@ -716,18 +726,15 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke if (mask & GROUP_UPDATE_FLAG_AURAS) { - uint64 auramask = player->GetAuraUpdateMask(); + const uint64& auramask = player->GetAuraUpdateMaskForRaid(); *data << uint64(auramask); for(uint32 i = 0; i < MAX_AURAS; ++i) { if(auramask & (uint64(1) << i)) { - uint32 updatedAura=player->GetUInt32Value(UNIT_FIELD_AURA + i); - *data << uint16(updatedAura); + AuraSlotEntry * pAura = player->GetVisibleAura(i); + *data << uint32(pAura ? pAura->m_spellId : 0); *data << uint8(1); - //TODO: find a safe place to do this cleanup - //if(!updatedAura) - //player->UnsetAuraUpdateMask(i); } } } @@ -760,17 +767,17 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke if (mask & GROUP_UPDATE_FLAG_PET_CUR_HP) { if(pet) - *data << (uint16) pet->GetHealth(); + *data << (uint32) pet->GetHealth(); else - *data << (uint16) 0; + *data << (uint32) 0; } if (mask & GROUP_UPDATE_FLAG_PET_MAX_HP) { if(pet) - *data << (uint16) pet->GetMaxHealth(); + *data << (uint32) pet->GetMaxHealth(); else - *data << (uint16) 0; + *data << (uint32) 0; } if (mask & GROUP_UPDATE_FLAG_PET_POWER_TYPE) @@ -801,18 +808,15 @@ void WorldSession::BuildPartyMemberStatsChangedPacket(Player *player, WorldPacke { if(pet) { - uint64 auramask = pet->GetAuraUpdateMask(); + const uint64& auramask = pet->GetAuraUpdateMaskForRaid(); *data << uint64(auramask); for(uint32 i = 0; i < MAX_AURAS; ++i) { if(auramask & (uint64(1) << i)) { - uint32 updatedAura=pet->GetUInt32Value(UNIT_FIELD_AURA + i); - *data << uint16(updatedAura); + AuraSlotEntry * pAura = pet->GetVisibleAura(i); + *data << uint32(pAura ? pAura->m_spellId : 0); *data << uint8(1); - //TODO: find a safe place to do this cleanup - //if(!updatedAura) - //pet->UnsetAuraUpdateMask(i); } } } @@ -834,6 +838,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) if(!player) { WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 3+4+2); + data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.appendPackGUID(Guid); data << (uint32) GROUP_UPDATE_FLAG_STATUS; data << (uint16) MEMBER_STATUS_OFFLINE; @@ -844,6 +849,7 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) Pet *pet = player->GetPet(); WorldPacket data(SMSG_PARTY_MEMBER_STATS_FULL, 4+2+2+2+1+2*6+8+1+8); + data << uint8(0); // only for SMSG_PARTY_MEMBER_STATS_FULL, probably arena/bg related data.append(player->GetPackGUID()); uint32 mask1 = 0x00040BFF; // common mask, real flags used 0x000040BFF @@ -853,8 +859,8 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) Powers powerType = player->getPowerType(); data << (uint32) mask1; // group update mask data << (uint16) MEMBER_STATUS_ONLINE; // member's online status - data << (uint16) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP - data << (uint16) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP + data << (uint32) player->GetHealth(); // GROUP_UPDATE_FLAG_CUR_HP + data << (uint32) player->GetMaxHealth(); // GROUP_UPDATE_FLAG_MAX_HP data << (uint8) powerType; // GROUP_UPDATE_FLAG_POWER_TYPE data << (uint16) player->GetPower(powerType); // GROUP_UPDATE_FLAG_CUR_POWER data << (uint16) player->GetMaxPower(powerType); // GROUP_UPDATE_FLAG_MAX_POWER @@ -868,11 +874,11 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) data << (uint64) auramask; // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { - if(uint32 aura = player->GetUInt32Value(UNIT_FIELD_AURA + i)) + if(AuraSlotEntry * pAura = player->GetVisibleAura(i)) { auramask |= (uint64(1) << i); - data << uint16(aura); - data << uint8(1); + data << (uint32) pAura->m_spellId; + data << (uint8) 1; } } data.put<uint64>(maskPos,auramask); // GROUP_UPDATE_FLAG_AURAS @@ -883,8 +889,8 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) data << (uint64) pet->GetGUID(); // GROUP_UPDATE_FLAG_PET_GUID data << pet->GetName(); // GROUP_UPDATE_FLAG_PET_NAME data << (uint16) pet->GetDisplayId(); // GROUP_UPDATE_FLAG_PET_MODEL_ID - data << (uint16) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP - data << (uint16) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP + data << (uint32) pet->GetHealth(); // GROUP_UPDATE_FLAG_PET_CUR_HP + data << (uint32) pet->GetMaxHealth(); // GROUP_UPDATE_FLAG_PET_MAX_HP data << (uint8) petpowertype; // GROUP_UPDATE_FLAG_PET_POWER_TYPE data << (uint16) pet->GetPower(petpowertype); // GROUP_UPDATE_FLAG_PET_CUR_POWER data << (uint16) pet->GetMaxPower(petpowertype); // GROUP_UPDATE_FLAG_PET_MAX_POWER @@ -894,10 +900,10 @@ void WorldSession::HandleRequestPartyMemberStatsOpcode( WorldPacket &recv_data ) data << (uint64) petauramask; // placeholder for(uint8 i = 0; i < MAX_AURAS; ++i) { - if(uint32 petaura = pet->GetUInt32Value(UNIT_FIELD_AURA + i)) + if(AuraSlotEntry * pAura = pet->GetVisibleAura(i)) { petauramask |= (uint64(1) << i); - data << (uint16) petaura; + data << (uint32) pAura->m_spellId; data << (uint8) 1; } } diff --git a/src/game/GroupRefManager.h b/src/game/GroupRefManager.h index 1bef31f076f..b17c3394b94 100644 --- a/src/game/GroupRefManager.h +++ b/src/game/GroupRefManager.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/GroupReference.cpp b/src/game/GroupReference.cpp index 25ea473309a..e9994a133ca 100644 --- a/src/game/GroupReference.cpp +++ b/src/game/GroupReference.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/GroupReference.h b/src/game/GroupReference.h index 66e91bd3a8a..60948435533 100644 --- a/src/game/GroupReference.h +++ b/src/game/GroupReference.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp index d3c3d9a7330..4ec794767ea 100644 --- a/src/game/GuardAI.cpp +++ b/src/game/GuardAI.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/GuardAI.h b/src/game/GuardAI.h index 30f76dd509a..2f91f359115 100644 --- a/src/game/GuardAI.h +++ b/src/game/GuardAI.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index d16274dbf5b..f32cbbeb7fa 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -785,6 +785,7 @@ void Guild::Query(WorldSession *session) data << uint32(BorderStyle); data << uint32(BorderColor); data << uint32(BackgroundColor); + data << uint32(0); // something new in WotLK session->SendPacket( &data ); sLog.outDebug( "WORLD: Sent (SMSG_GUILD_QUERY_RESPONSE)" ); @@ -1212,18 +1213,19 @@ void Guild::LoadGuildBankFromDB() delete result; - // 0 1 2 3 - result = CharacterDatabase.PQuery("SELECT TabId, SlotId, item_guid, item_entry FROM guild_bank_item WHERE guildid='%u' ORDER BY TabId", Id); + // data needs to be at first place for Item::LoadFromDB + // 0 1 2 3 4 + result = CharacterDatabase.PQuery("SELECT data, TabId, SlotId, item_guid, item_entry FROM guild_bank_item JOIN item_instance ON item_guid = guid WHERE guildid='%u' ORDER BY TabId", Id); if(!result) return; do { Field *fields = result->Fetch(); - uint8 TabId = fields[0].GetUInt8(); - uint8 SlotId = fields[1].GetUInt8(); - uint32 ItemGuid = fields[2].GetUInt32(); - uint32 ItemEntry = fields[3].GetUInt32(); + uint8 TabId = fields[1].GetUInt8(); + uint8 SlotId = fields[2].GetUInt8(); + uint32 ItemGuid = fields[3].GetUInt32(); + uint32 ItemEntry = fields[4].GetUInt32(); if (TabId >= purchased_tabs || TabId >= GUILD_BANK_MAX_TABS) { @@ -1246,7 +1248,7 @@ void Guild::LoadGuildBankFromDB() } Item *pItem = NewItemOrBag(proto); - if(!pItem->LoadFromDB(ItemGuid, 0)) + if(!pItem->LoadFromDB(ItemGuid, 0, result)) { CharacterDatabase.PExecute("DELETE FROM guild_bank_item WHERE guildid='%u' AND TabId='%u' AND SlotId='%u'", Id, uint32(TabId), uint32(SlotId)); sLog.outError("Item GUID %u not found in item_instance, deleting from Guild Bank!", ItemGuid); @@ -1602,7 +1604,21 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId) { data << uint8((*itr)->LogEntry); data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER)); - data << uint32((*itr)->ItemOrMoney); + if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_UNK1 || + (*itr)->LogEntry == GUILD_BANK_LOG_UNK2) + { + data << uint32((*itr)->ItemOrMoney); + } + else + { + data << uint32((*itr)->ItemOrMoney); + data << uint32((*itr)->ItemStackCount); + if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2) + data << uint8((*itr)->DestTabId); // moved tab + } data << uint32(time(NULL)-(*itr)->TimeStamp); } session->SendPacket(&data); @@ -1618,10 +1634,21 @@ void Guild::DisplayGuildBankLogs(WorldSession *session, uint8 TabId) { data << uint8((*itr)->LogEntry); data << uint64(MAKE_NEW_GUID((*itr)->PlayerGuid,0,HIGHGUID_PLAYER)); - data << uint32((*itr)->ItemOrMoney); - data << uint8((*itr)->ItemStackCount); - if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2) - data << uint8((*itr)->DestTabId); // moved tab + if ((*itr)->LogEntry == GUILD_BANK_LOG_DEPOSIT_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_WITHDRAW_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_REPAIR_MONEY || + (*itr)->LogEntry == GUILD_BANK_LOG_UNK1 || + (*itr)->LogEntry == GUILD_BANK_LOG_UNK2) + { + data << uint32((*itr)->ItemOrMoney); + } + else + { + data << uint32((*itr)->ItemOrMoney); + data << uint32((*itr)->ItemStackCount); + if ((*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM || (*itr)->LogEntry == GUILD_BANK_LOG_MOVE_ITEM2) + data << uint8((*itr)->DestTabId); // moved tab + } data << uint32(time(NULL)-(*itr)->TimeStamp); } session->SendPacket(&data); @@ -1703,7 +1730,7 @@ void Guild::AppendDisplayGuildBankSlot( WorldPacket& data, GuildBankTab const *t // SuffixFactor +4 data << (uint32) pItem->GetItemSuffixFactor(); // +12 // ITEM_FIELD_STACK_COUNT - data << uint8(pItem->GetCount()); + data << uint32(pItem->GetCount()); data << uint32(0); // +16 // Unknown value data << uint8(0); // unknown 2.4.2 if (uint32 Enchant0 = pItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT)) diff --git a/src/game/Guild.h b/src/game/Guild.h index 683ff980e3a..a1bd6d2e36f 100644 --- a/src/game/Guild.h +++ b/src/game/Guild.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -56,7 +56,8 @@ enum GuildRankRights GR_RIGHT_REPAIR_FROM_GUILD = 0x00020000, // unused in 2.4.x?, Remove money withdraw capacity GR_RIGHT_WITHDRAW_REPAIR = 0x00040000, // withdraw for repair GR_RIGHT_WITHDRAW_GOLD = 0x00080000, // withdraw gold - GR_RIGHT_ALL = 0x000FF1FF + GR_RIGHT_CREATE_GUILD_EVENT = 0x00100000, // wotlk + GR_RIGHT_ALL = 0x001FF1FF }; enum Typecommand @@ -156,6 +157,8 @@ enum GuildBankLogEntries GUILD_BANK_LOG_WITHDRAW_MONEY = 5, GUILD_BANK_LOG_REPAIR_MONEY = 6, GUILD_BANK_LOG_MOVE_ITEM2 = 7, + GUILD_BANK_LOG_UNK1 = 8, + GUILD_BANK_LOG_UNK2 = 9, }; enum GuildEventLogEntryTypes @@ -217,12 +220,12 @@ struct GuildBankTab struct GuildItemPosCount { - GuildItemPosCount(uint8 _slot, uint8 _count) : slot(_slot), count(_count) {} + GuildItemPosCount(uint8 _slot, uint32 _count) : slot(_slot), count(_count) {} bool isContainedIn(std::vector<GuildItemPosCount> const& vec) const; uint8 slot; - uint8 count; + uint32 count; }; typedef std::vector<GuildItemPosCount> GuildItemPosCountVec; diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index 4711f2d0902..f1a59814d57 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -375,7 +375,7 @@ void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket) guild->ChangeRank(plGuid, (slot->RankId+1)); // Put record into guildlog - guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), (slot->RankId)); + guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), slot->RankId); WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size data << (uint8)GE_DEMOTION; diff --git a/src/game/HomeMovementGenerator.cpp b/src/game/HomeMovementGenerator.cpp index 0f5b9b2543b..4fa3ca6e8bd 100644 --- a/src/game/HomeMovementGenerator.cpp +++ b/src/game/HomeMovementGenerator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/HomeMovementGenerator.h b/src/game/HomeMovementGenerator.h index a116027608f..77e78ca23d3 100644 --- a/src/game/HomeMovementGenerator.h +++ b/src/game/HomeMovementGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/HostilRefManager.cpp b/src/game/HostilRefManager.cpp index a2928158a2c..aed4c8d02eb 100644 --- a/src/game/HostilRefManager.cpp +++ b/src/game/HostilRefManager.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/HostilRefManager.h b/src/game/HostilRefManager.h index 4d049b234c0..8c4ac623ac0 100644 --- a/src/game/HostilRefManager.h +++ b/src/game/HostilRefManager.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/IdleMovementGenerator.cpp b/src/game/IdleMovementGenerator.cpp index 6b68dd8eeed..b8910f555d0 100644 --- a/src/game/IdleMovementGenerator.cpp +++ b/src/game/IdleMovementGenerator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/IdleMovementGenerator.h b/src/game/IdleMovementGenerator.h index 8a8aece5458..19618be8e86 100644 --- a/src/game/IdleMovementGenerator.h +++ b/src/game/IdleMovementGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/InstanceData.cpp b/src/game/InstanceData.cpp index c605de2c453..79b1f8bcbb3 100644 --- a/src/game/InstanceData.cpp +++ b/src/game/InstanceData.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/InstanceData.h b/src/game/InstanceData.h index 8fea525a6e2..146e955f8fe 100644 --- a/src/game/InstanceData.h +++ b/src/game/InstanceData.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/InstanceSaveMgr.cpp b/src/game/InstanceSaveMgr.cpp index cb95dac6978..ad827a07bf2 100644 --- a/src/game/InstanceSaveMgr.cpp +++ b/src/game/InstanceSaveMgr.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * * This program is free software; you can redistribute it and/or modify @@ -270,7 +270,7 @@ void InstanceSaveManager::CleanupInstances() // creature_respawn and gameobject_respawn are in another database // first, obtain total instance set - std::set< uint32 > InstanceSet; + std::set<uint32> InstanceSet; QueryResult *result = CharacterDatabase.Query("SELECT id FROM instance"); if( result ) { @@ -322,7 +322,7 @@ void InstanceSaveManager::PackInstances() // TODO: this can be done a LOT more efficiently // obtain set of all associations - std::set< uint32 > InstanceSet; + std::set<uint32> InstanceSet; // all valid ids are in the instance table // any associations to ids not in this table are assumed to be @@ -344,7 +344,7 @@ void InstanceSaveManager::PackInstances() uint32 InstanceNumber = 1; // we do assume std::set is sorted properly on integer value - for (std::set< uint32 >::iterator i = InstanceSet.begin(); i != InstanceSet.end(); ++i) + for (std::set<uint32>::iterator i = InstanceSet.begin(); i != InstanceSet.end(); ++i) { if (*i != InstanceNumber) { @@ -361,8 +361,8 @@ void InstanceSaveManager::PackInstances() bar.step(); } - sLog.outString(); sLog.outString( ">> Instance numbers remapped, next instance id is %u", InstanceNumber ); + sLog.outString(); } void InstanceSaveManager::LoadResetTimes() @@ -454,7 +454,7 @@ void InstanceSaveManager::LoadResetTimes() // add the global reset times to the priority queue for(uint32 i = 0; i < sInstanceTemplate.MaxEntry; i++) { - InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(i); + InstanceTemplate const* temp = objmgr.GetInstanceTemplate(i); if(!temp) continue; // only raid/heroic maps have a global reset time const MapEntry* entry = sMapStore.LookupEntry(temp->map); @@ -583,7 +583,7 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe { // global reset for all instances of the given map // note: this isn't fast but it's meant to be executed very rarely - Map *map = (MapInstanced*)MapManager::Instance().GetBaseMap(mapid); + Map const *map = MapManager::Instance().GetBaseMap(mapid); if(!map->Instanceable()) return; uint64 now = (uint64)time(NULL); @@ -591,7 +591,7 @@ void InstanceSaveManager::_ResetOrWarnAll(uint32 mapid, bool warn, uint32 timeLe if(!warn) { // this is called one minute before the reset time - InstanceTemplate* temp = (InstanceTemplate*)objmgr.GetInstanceTemplate(mapid); + InstanceTemplate const* temp = objmgr.GetInstanceTemplate(mapid); if(!temp || !temp->reset_delay) { sLog.outError("InstanceSaveManager::ResetOrWarnAll: no instance template or reset delay for map %d", mapid); diff --git a/src/game/InstanceSaveMgr.h b/src/game/InstanceSaveMgr.h index 7dcf13aede8..f868f2e8094 100644 --- a/src/game/InstanceSaveMgr.h +++ b/src/game/InstanceSaveMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * * This program is free software; you can redistribute it and/or modify diff --git a/src/game/Item.cpp b/src/game/Item.cpp index b0c2109a5b5..e8280711143 100644 --- a/src/game/Item.cpp +++ b/src/game/Item.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -206,6 +206,10 @@ bool ItemCanGoIntoBag(ItemPrototype const *pProto, ItemPrototype const *pBagProt if(!(pProto->BagFamily & BAG_FAMILY_MASK_LEATHERWORKING_SUPP)) return false; return true; + case ITEM_SUBCLASS_INSCRIPTION_CONTAINER: + if(!(pProto->BagFamily & BAG_FAMILY_MASK_INSCRIPTION_SUPP)) + return false; + return true; default: return false; } @@ -284,7 +288,7 @@ void Item::UpdateDuration(Player* owner, uint32 diff) } SetUInt32Value(ITEM_FIELD_DURATION, GetUInt32Value(ITEM_FIELD_DURATION) - diff); - SetState(ITEM_CHANGED); // save new time in database + SetState(ITEM_CHANGED, owner); // save new time in database } void Item::SaveToDB() @@ -450,7 +454,7 @@ uint32 Item::GetSkill() const static uint32 item_armor_skills[MAX_ITEM_SUBCLASS_ARMOR] = { - 0,SKILL_CLOTH,SKILL_LEATHER,SKILL_MAIL,SKILL_PLATE_MAIL,0,SKILL_SHIELD,0,0,0 + 0,SKILL_CLOTH,SKILL_LEATHER,SKILL_MAIL,SKILL_PLATE_MAIL,0,SKILL_SHIELD,0,0,0,0 }; ItemPrototype const* proto = GetProto(); @@ -765,9 +769,9 @@ void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint if((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges)) return; - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id); - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration); - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET,id); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges); SetState(ITEM_CHANGED); } @@ -776,7 +780,7 @@ void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration) if(GetEnchantmentDuration(slot) == duration) return; - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET,duration); SetState(ITEM_CHANGED); } @@ -785,7 +789,7 @@ void Item::SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges) if(GetEnchantmentCharges(slot) == charges) return; - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET,charges); SetState(ITEM_CHANGED); } @@ -795,7 +799,7 @@ void Item::ClearEnchantment(EnchantmentSlot slot) return; for(uint8 x = 0; x < 3; ++x) - SetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + x, 0); + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + x, 0); SetState(ITEM_CHANGED); } @@ -886,8 +890,8 @@ Item* Item::CreateItem( uint32 item, uint32 count, Player const* player ) ItemPrototype const *pProto = objmgr.GetItemPrototype( item ); if( pProto ) { - if ( count > pProto->Stackable ) - count = pProto->Stackable; + if ( count > pProto->GetMaxStackSize()) + count = pProto->GetMaxStackSize(); assert(count !=0 && "pProto->Stackable==0 but checked at loading already"); diff --git a/src/game/Item.h b/src/game/Item.h index 72c09b0c1da..8869f2ac013 100644 --- a/src/game/Item.h +++ b/src/game/Item.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -148,29 +148,32 @@ enum SellFailure // -1 from client enchantment slot number enum EnchantmentSlot { - PERM_ENCHANTMENT_SLOT = 0, - TEMP_ENCHANTMENT_SLOT = 1, - SOCK_ENCHANTMENT_SLOT = 2, - SOCK_ENCHANTMENT_SLOT_2 = 3, - SOCK_ENCHANTMENT_SLOT_3 = 4, - BONUS_ENCHANTMENT_SLOT = 5, - MAX_INSPECTED_ENCHANTMENT_SLOT = 6, - - PROP_ENCHANTMENT_SLOT_0 = 6, // used with RandomSuffix - PROP_ENCHANTMENT_SLOT_1 = 7, // used with RandomSuffix - PROP_ENCHANTMENT_SLOT_2 = 8, // used with RandomSuffix and RandomProperty - PROP_ENCHANTMENT_SLOT_3 = 9, // used with RandomProperty - PROP_ENCHANTMENT_SLOT_4 = 10, // used with RandomProperty - MAX_ENCHANTMENT_SLOT = 11 + PERM_ENCHANTMENT_SLOT = 0, + TEMP_ENCHANTMENT_SLOT = 1, + SOCK_ENCHANTMENT_SLOT = 2, + SOCK_ENCHANTMENT_SLOT_2 = 3, + SOCK_ENCHANTMENT_SLOT_3 = 4, + BONUS_ENCHANTMENT_SLOT = 5, + PRISMATIC_ENCHANTMENT_SLOT = 6, // added at apply special permanent enchantment + MAX_INSPECTED_ENCHANTMENT_SLOT = 7, + + PROP_ENCHANTMENT_SLOT_0 = 7, // used with RandomSuffix + PROP_ENCHANTMENT_SLOT_1 = 8, // used with RandomSuffix + PROP_ENCHANTMENT_SLOT_2 = 9, // used with RandomSuffix and RandomProperty + PROP_ENCHANTMENT_SLOT_3 = 10, // used with RandomProperty + PROP_ENCHANTMENT_SLOT_4 = 11, // used with RandomProperty + MAX_ENCHANTMENT_SLOT = 12 }; -#define MAX_VISIBLE_ITEM_OFFSET 16 // 16 fields per visible item (creator(2) + enchantments(12) + properties(1) + pad(1)) +#define MAX_VISIBLE_ITEM_OFFSET 18 // 18 fields per visible item (creator(2) + enchantments(13) + properties(1) + seed(1) + pad(1)) + +#define MAX_GEM_SOCKETS 3 // (BONUS_ENCHANTMENT_SLOT-SOCK_ENCHANTMENT_SLOT) enum EnchantmentOffset { ENCHANTMENT_ID_OFFSET = 0, ENCHANTMENT_DURATION_OFFSET = 1, - ENCHANTMENT_CHARGES_OFFSET = 2 + ENCHANTMENT_CHARGES_OFFSET = 2 // now here not only charges, but something new in wotlk }; #define MAX_ENCHANTMENT_OFFSET 3 @@ -211,6 +214,7 @@ class TRINITY_DLL_SPEC Item : public Object void SetBinding(bool val) { ApplyModFlag(ITEM_FIELD_FLAGS,ITEM_FLAGS_BINDED,val); } bool IsSoulBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BINDED); } + bool IsAccountBound() const { return HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_BOA); } bool IsBindedNotWith(uint64 guid) const { return IsSoulBound() && GetOwnerGUID()!= guid; } bool IsBoundByEnchant() const; virtual void SaveToDB(); @@ -230,7 +234,7 @@ class TRINITY_DLL_SPEC Item : public Object uint32 GetCount() const { return GetUInt32Value (ITEM_FIELD_STACK_COUNT); } void SetCount(uint32 value) { SetUInt32Value (ITEM_FIELD_STACK_COUNT, value); } - uint32 GetMaxStackCount() const { return GetProto()->Stackable; } + uint32 GetMaxStackCount() const { return GetProto()->GetMaxStackSize(); } uint8 GetGemCountWithID(uint32 GemID) const; uint8 GetSlot() const {return m_slot;} @@ -256,9 +260,9 @@ class TRINITY_DLL_SPEC Item : public Object void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration); void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges); void ClearEnchantment(EnchantmentSlot slot); - uint32 GetEnchantmentId(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET);} - uint32 GetEnchantmentDuration(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET);} - uint32 GetEnchantmentCharges(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET);} + uint32 GetEnchantmentId(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET);} + uint32 GetEnchantmentDuration(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET);} + uint32 GetEnchantmentCharges(EnchantmentSlot slot) const { return GetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET);} void SendTimeUpdate(Player* owner); void UpdateDuration(Player* owner, uint32 diff); diff --git a/src/game/ItemEnchantmentMgr.cpp b/src/game/ItemEnchantmentMgr.cpp index 52a2e5dc1eb..305e3a64ebc 100644 --- a/src/game/ItemEnchantmentMgr.cpp +++ b/src/game/ItemEnchantmentMgr.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ItemEnchantmentMgr.h b/src/game/ItemEnchantmentMgr.h index 97053c1ec36..0feed4319d5 100644 --- a/src/game/ItemEnchantmentMgr.h +++ b/src/game/ItemEnchantmentMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 085c9553a30..3b3a23acfce 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -324,7 +324,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->ItemId; data << pProto->Class; data << pProto->SubClass; - data << uint32(-1); // new 2.0.3, not exist in wdb cache? + data << int32(pProto->Unk0); // new 2.0.3, not exist in wdb cache? data << Name; data << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name... data << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00); @@ -346,14 +346,17 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->RequiredCityRank; data << pProto->RequiredReputationFaction; data << pProto->RequiredReputationRank; - data << pProto->MaxCount; - data << pProto->Stackable; + data << int32(pProto->MaxCount); + data << int32(pProto->Stackable); data << pProto->ContainerSlots; - for(int i = 0; i < 10; i++) + data << pProto->StatsCount; // item stats count + for(int i = 0; i < pProto->StatsCount; i++) { data << pProto->ItemStat[i].ItemStatType; data << pProto->ItemStat[i].ItemStatValue; } + data << pProto->ScalingStatDistribution; // scaling stats distribution + data << pProto->ScalingStatValue; // some kind of flags used to determine stat values column for(int i = 0; i < 5; i++) { data << pProto->Damage[i].DamageMin; @@ -417,7 +420,7 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->PageMaterial; data << pProto->StartQuest; data << pProto->LockID; - data << pProto->Material; + data << int32(pProto->Material); data << pProto->Sheath; data << pProto->RandomProperty; data << pProto->RandomSuffix; @@ -437,7 +440,8 @@ void WorldSession::HandleItemQuerySingleOpcode( WorldPacket & recv_data ) data << pProto->GemProperties; data << pProto->RequiredDisenchantSkill; data << pProto->ArmorDamageModifier; - data << uint32(0); // added in 2.4.2.8209, duration (seconds) + data << pProto->Duration; // added in 2.4.2.8209, duration (seconds) + data << pProto->ItemLimitCategory; // WotLK, ItemLimitCategory SendPacket( &data ); } else @@ -738,7 +742,7 @@ void WorldSession::SendListInventory( uint64 vendorguid ) float discountMod = _player->GetReputationPriceDiscount(pCreature); - for(int i = 0; i < numitems; i++ ) + for(int i = 0; i < numitems; ++i ) { if(VendorItem const* crItem = vItems->GetItem(i)) { @@ -845,6 +849,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPacket& /*recvPacket*/) if (_player->GetMoney() < price) return; + _player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT, slot); _player->SetByteValue(PLAYER_BYTES_2, 2, slot); _player->ModifyMoney(-int32(price)); } @@ -1106,57 +1111,80 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) { sLog.outDebug("WORLD: CMSG_SOCKET_GEMS"); - CHECK_PACKET_SIZE(recv_data,8*4); + CHECK_PACKET_SIZE(recv_data,8+8*MAX_GEM_SOCKETS); - uint64 guids[4]; - uint32 GemEnchants[3], OldEnchants[3]; - Item *Gems[3]; - bool SocketBonusActivated, SocketBonusToBeActivated; + uint64 item_guid; + uint64 gem_guids[MAX_GEM_SOCKETS]; - for(int i = 0; i < 4; i++) - recv_data >> guids[i]; - - if(!guids[0]) + recv_data >> item_guid; + if(!item_guid) return; + for(int i = 0; i < MAX_GEM_SOCKETS; ++i) + recv_data >> gem_guids[i]; + //cheat -> tried to socket same gem multiple times - if((guids[1] && (guids[1] == guids[2] || guids[1] == guids[3])) || (guids[2] && (guids[2] == guids[3]))) + if ((gem_guids[0] && (gem_guids[0] == gem_guids[1] || gem_guids[0] == gem_guids[2])) || + (gem_guids[1] && (gem_guids[1] == gem_guids[2]))) return; - Item *itemTarget = _player->GetItemByGuid(guids[0]); + Item *itemTarget = _player->GetItemByGuid(item_guid); if(!itemTarget) //missing item to socket return; + ItemPrototype const* itemProto = itemTarget->GetProto(); + if(!itemProto) + return; + //this slot is excepted when applying / removing meta gem bonus uint8 slot = itemTarget->IsEquipped() ? itemTarget->GetSlot() : NULL_SLOT; - for(int i = 0; i < 3; i++) - Gems[i] = guids[i + 1] ? _player->GetItemByGuid(guids[i + 1]) : NULL; + Item *Gems[MAX_GEM_SOCKETS]; + for(int i = 0; i < MAX_GEM_SOCKETS; ++i) + Gems[i] = gem_guids[i] ? _player->GetItemByGuid(gem_guids[i]) : NULL; - GemPropertiesEntry const *GemProps[3]; - for(int i = 0; i < 3; ++i) //get geminfo from dbc storage - { + GemPropertiesEntry const *GemProps[MAX_GEM_SOCKETS]; + for(int i = 0; i < MAX_GEM_SOCKETS; ++i) //get geminfo from dbc storage GemProps[i] = (Gems[i]) ? sGemPropertiesStore.LookupEntry(Gems[i]->GetProto()->GemProperties) : NULL; - } - for(int i = 0; i < 3; ++i) //check for hack maybe + for(int i = 0; i < MAX_GEM_SOCKETS; ++i) //check for hack maybe { - // tried to put gem in socket where no socket exists / tried to put normal gem in meta socket + if (!GemProps[i]) + continue; + + // tried to put gem in socket where no socket exists (take care about prismatic sockets) + if (!itemProto->Socket[i].Color) + { + // no prismatic socket + if(!itemTarget->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT)) + return; + + // not first not-colored (not normaly used) socket + if(i!=0 && !itemProto->Socket[i-1].Color && (i+1 >= MAX_GEM_SOCKETS || itemProto->Socket[i+1].Color)) + return; + + // ok, this is first not colored socket for item with prismatic socket + } + + // tried to put normal gem in meta socket + if (itemProto->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META) + return; + // tried to put meta gem in normal socket - if( GemProps[i] && ( !itemTarget->GetProto()->Socket[i].Color || - itemTarget->GetProto()->Socket[i].Color == SOCKET_COLOR_META && GemProps[i]->color != SOCKET_COLOR_META || - itemTarget->GetProto()->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META ) ) + if (itemProto->Socket[i].Color != SOCKET_COLOR_META && GemProps[i]->color == SOCKET_COLOR_META) return; } - for(int i = 0; i < 3; ++i) //get new and old enchantments + uint32 GemEnchants[MAX_GEM_SOCKETS]; + uint32 OldEnchants[MAX_GEM_SOCKETS]; + for(int i = 0; i < MAX_GEM_SOCKETS; ++i) //get new and old enchantments { GemEnchants[i] = (GemProps[i]) ? GemProps[i]->spellitemenchantement : 0; OldEnchants[i] = itemTarget->GetEnchantmentId(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i)); } // check unique-equipped conditions - for(int i = 0; i < 3; ++i) + for(int i = 0; i < MAX_GEM_SOCKETS; ++i) { if (Gems[i] && (Gems[i]->GetProto()->Flags & ITEM_FLAGS_UNIQUE_EQUIPPED)) { @@ -1171,7 +1199,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) } // continue check for case when attempt add 2 similar unique equipped gems in one item. - for (int j = 0; j < 3; ++j) + for (int j = 0; j < MAX_GEM_SOCKETS; ++j) { if ((i != j) && (Gems[j]) && (Gems[i]->GetProto()->ItemId == Gems[j]->GetProto()->ItemId)) { @@ -1179,7 +1207,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) return; } } - for (int j = 0; j < 3; ++j) + for (int j = 0; j < MAX_GEM_SOCKETS; ++j) { if (OldEnchants[j]) { @@ -1197,29 +1225,29 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recv_data) } } - SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus + bool SocketBonusActivated = itemTarget->GemsFitSockets(); //save state of socketbonus _player->ToggleMetaGemsActive(slot, false); //turn off all metagems (except for the target item) //if a meta gem is being equipped, all information has to be written to the item before testing if the conditions for the gem are met //remove ALL enchants - for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) + for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot) _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),false); - for(int i = 0; i < 3; ++i) + for(int i = 0; i < MAX_GEM_SOCKETS; ++i) { if(GemEnchants[i]) { itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i],0,0); - if(Item* guidItem = _player->GetItemByGuid(guids[i + 1])) + if(Item* guidItem = _player->GetItemByGuid(gem_guids[i])) _player->DestroyItem(guidItem->GetBagSlot(), guidItem->GetSlot(), true ); } } - for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot) + for(uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+MAX_GEM_SOCKETS; ++enchant_slot) _player->ApplyEnchantment(itemTarget,EnchantmentSlot(enchant_slot),true); - SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state + bool SocketBonusToBeActivated = itemTarget->GemsFitSockets();//current socketbonus state if(SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change... { _player->ApplyEnchantment(itemTarget,BONUS_ENCHANTMENT_SLOT,false); diff --git a/src/game/ItemPrototype.h b/src/game/ItemPrototype.h index 1ca412d246a..c23c0d5978c 100644 --- a/src/game/ItemPrototype.h +++ b/src/game/ItemPrototype.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,10 +57,18 @@ enum ItemModType ITEM_MOD_CRIT_TAKEN_RATING = 34, ITEM_MOD_RESILIENCE_RATING = 35, ITEM_MOD_HASTE_RATING = 36, - ITEM_MOD_EXPERTISE_RATING = 37 + ITEM_MOD_EXPERTISE_RATING = 37, + ITEM_MOD_ATTACK_POWER = 38, + ITEM_MOD_RANGED_ATTACK_POWER = 39, + ITEM_MOD_FERAL_ATTACK_POWER = 40, + ITEM_MOD_SPELL_HEALING_DONE = 41, + ITEM_MOD_SPELL_DAMAGE_DONE = 42, + ITEM_MOD_MANA_REGENERATION = 43, + ITEM_MOD_ARMOR_PENETRATION_RATING = 44, + ITEM_MOD_SPELL_POWER = 45 }; -#define MAX_ITEM_MOD 38 +#define MAX_ITEM_MOD 46 enum ItemSpelltriggerType { @@ -68,6 +76,12 @@ enum ItemSpelltriggerType ITEM_SPELLTRIGGER_ON_EQUIP = 1, ITEM_SPELLTRIGGER_CHANCE_ON_HIT = 2, ITEM_SPELLTRIGGER_SOULSTONE = 4, + /* + * ItemSpelltriggerType 5 might have changed on 2.4.3/3.0.3: Such auras + * will be applied on item pickup and removed on item loss - maybe on the + * other hand the item is destroyed if the aura is removed ("removed on + * death" of spell 57348 makes me think so) + */ ITEM_SPELLTRIGGER_ON_NO_DELAY_USE = 5, // no equip cooldown ITEM_SPELLTRIGGER_LEARN_SPELL_ID = 6 // used in item_template.spell_2 with spell_id with SPELL_GENERIC_LEARN in spell_1 }; @@ -96,6 +110,7 @@ enum ITEM_FLAGS ITEM_FLAGS_WRAPPER = 0x00000200, // used or not used wrapper ITEM_FLAGS_PARTY_LOOT = 0x00000800, // determines if item is party loot or not ITEM_FLAGS_CHARTER = 0x00002000, // arena/guild charter + ITEM_FLAGS_PROSPECTABLE = 0x00040000, ITEM_FLAGS_UNIQUE_EQUIPPED = 0x00080000, ITEM_FLAGS_USEABLE_IN_ARENA = 0x00200000, ITEM_FLAGS_THROWABLE = 0x00400000, // not used in game for check trow possibility, only for item in game tooltip @@ -185,10 +200,11 @@ enum ItemClass ITEM_CLASS_QUEST = 12, ITEM_CLASS_KEY = 13, ITEM_CLASS_PERMANENT = 14, - ITEM_CLASS_JUNK = 15 + ITEM_CLASS_MISC = 15, + ITEM_CLASS_GLYPH = 16 }; -#define MAX_ITEM_CLASS 16 +#define MAX_ITEM_CLASS 17 enum ItemSubclassConsumable { @@ -214,10 +230,11 @@ enum ItemSubclassContainer ITEM_SUBCLASS_ENGINEERING_CONTAINER = 4, ITEM_SUBCLASS_GEM_CONTAINER = 5, ITEM_SUBCLASS_MINING_CONTAINER = 6, - ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7 + ITEM_SUBCLASS_LEATHERWORKING_CONTAINER = 7, + ITEM_SUBCLASS_INSCRIPTION_CONTAINER = 8 }; -#define MAX_ITEM_SUBCLASS_CONTAINER 8 +#define MAX_ITEM_SUBCLASS_CONTAINER 9 enum ItemSubclassWeapon { @@ -272,10 +289,11 @@ enum ItemSubclassArmor ITEM_SUBCLASS_ARMOR_SHIELD = 6, ITEM_SUBCLASS_ARMOR_LIBRAM = 7, ITEM_SUBCLASS_ARMOR_IDOL = 8, - ITEM_SUBCLASS_ARMOR_TOTEM = 9 + ITEM_SUBCLASS_ARMOR_TOTEM = 9, + ITEM_SUBCLASS_ARMOR_SIGIL = 10 }; -#define MAX_ITEM_SUBCLASS_ARMOR 10 +#define MAX_ITEM_SUBCLASS_ARMOR 11 enum ItemSubclassReagent { @@ -310,10 +328,12 @@ enum ItemSubclassTradeGoods ITEM_SUBCLASS_ELEMENTAL = 10, ITEM_SUBCLASS_TRADE_GOODS_OTHER = 11, ITEM_SUBCLASS_ENCHANTING = 12, - ITEM_SUBCLASS_MATERIAL = 13 // Added in 2.4.2 + ITEM_SUBCLASS_MATERIAL = 13, + ITEM_SUBCLASS_ARMOR_ENCHANTMENT = 14, + ITEM_SUBCLASS_WEAPON_ENCHANTMENT = 15 }; -#define MAX_ITEM_SUBCLASS_TRADE_GOODS 14 +#define MAX_ITEM_SUBCLASS_TRADE_GOODS 16 enum ItemSubclassGeneric { @@ -423,7 +443,8 @@ const uint32 MaxItemSubclassValues[MAX_ITEM_CLASS] = MAX_ITEM_SUBCLASS_QUEST, MAX_ITEM_SUBCLASS_KEY, MAX_ITEM_SUBCLASS_PERMANENT, - MAX_ITEM_SUBCLASS_JUNK + MAX_ITEM_SUBCLASS_JUNK, + MAX_ITEM_SUBCLASS_GLYPH }; inline uint8 ItemSubClassToDurabilityMultiplierId(uint32 ItemClass, uint32 ItemSubClass) @@ -477,7 +498,7 @@ struct ItemPrototype uint32 ItemId; uint32 Class; // id from ItemClass.dbc uint32 SubClass; // id from ItemSubClass.dbc - uint32 Unk0; + int32 Unk0; char* Name1; uint32 DisplayInfoID; // id from ItemDisplayInfo.dbc uint32 Quality; @@ -497,10 +518,13 @@ struct ItemPrototype uint32 RequiredCityRank; uint32 RequiredReputationFaction; // id from Faction.dbc uint32 RequiredReputationRank; - uint32 MaxCount; - uint32 Stackable; + int32 MaxCount; // <=0: no limit + int32 Stackable; // 0: not allowed, -1: put in player coin info tab and don't limit stacking (so 1 slot) uint32 ContainerSlots; + uint32 StatsCount; _ItemStat ItemStat[10]; + uint32 ScalingStatDistribution; // id from ScalingStatDistribution.dbc + uint32 ScalingStatValue; // mask for selecting column in ScalingStatValues.dbc _Damage Damage[5]; uint32 Armor; uint32 HolyRes; @@ -520,7 +544,7 @@ struct ItemPrototype uint32 PageMaterial; uint32 StartQuest; // id from QuestCache.wdb uint32 LockID; - uint32 Material; // id from Material.dbc + int32 Material; // id from Material.dbc uint32 Sheath; uint32 RandomProperty; // id from ItemRandomProperties.dbc uint32 RandomSuffix; // id from ItemRandomSuffix.dbc @@ -536,12 +560,13 @@ struct ItemPrototype uint32 GemProperties; // id from GemProperties.dbc uint32 RequiredDisenchantSkill; float ArmorDamageModifier; + int32 Duration; // negative = realtime, positive = ingame time + uint32 ItemLimitCategory; // id from ItemLimitCategory.dbc uint32 ScriptId; uint32 DisenchantID; uint32 FoodType; uint32 MinMoneyLoot; uint32 MaxMoneyLoot; - int32 Duration; // negative = realtime, positive = ingame time // helpers bool CanChangeEquipStateInCombat() const @@ -563,6 +588,71 @@ struct ItemPrototype return false; } + + uint32 GetScalingStatValuesColumn() const + { + if(ScalingStatValue & 0x00000001) // stat mod + return 0; + if(ScalingStatValue & 0x00000002) // stat mod + return 1; + if(ScalingStatValue & 0x00000004) // stat mod + return 2; + if(ScalingStatValue & 0x00000008) // stat mod + return 3; + if(ScalingStatValue & 0x00000010) // stat mod + return 4; + if(ScalingStatValue & 0x00000020) // armor mod + return 5; + if(ScalingStatValue & 0x00000040) // armor mod + return 6; + if(ScalingStatValue & 0x00000080) // armor mod + return 7; + if(ScalingStatValue & 0x00000100) // armor mod + return 8; + if(ScalingStatValue & 0x00000200) // damage mod + return 9; + if(ScalingStatValue & 0x00000400) // damage mod + return 10; + if(ScalingStatValue & 0x00000800) // damage mod + return 11; + if(ScalingStatValue & 0x00001000) // damage mod + return 12; + if(ScalingStatValue & 0x00002000) // damage mod + return 13; + if(ScalingStatValue & 0x00004000) // damage mod + return 14; + if(ScalingStatValue & 0x00008000) // spell power + return 15; + if(ScalingStatValue & 0x00020000) // feral AP + return 16; + + return 0; + } + + uint32 GetMaxStackSize() const { return Stackable > 0 ? uint32(Stackable) : uint32(0x7FFFFFFF-1); } + + float getDPS() const + { + if (Delay == 0) + return 0; + float temp = 0; + for (int i=0;i<5;++i) + temp+=Damage[i].DamageMin + Damage[i].DamageMax; + return temp*500/Delay; + } + + int32 getFeralBonus() const + { + // 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc + if (Class == ITEM_CLASS_WEAPON && (1<<SubClass)&0x02A5F3) + { + int32 bonus = int32(getDPS()*14.0f) - 767; + if (bonus < 0) + return 0; + return bonus; + } + return 0; + } }; struct ItemLocale diff --git a/src/game/LFGHandler.cpp b/src/game/LFGHandler.cpp index a3379c4d79b..182e89a42c5 100644 --- a/src/game/LFGHandler.cpp +++ b/src/game/LFGHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Language.h b/src/game/Language.h index 590c21e715b..72b30b1448f 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -170,7 +170,9 @@ enum TrinityStrings LANG_SOUND_NOT_EXIST = 170, LANG_TELEPORTED_TO_BY_CONSOLE = 171, LANG_CONSOLE_COMMAND = 172, - // Room for more level 1 173-199 not used + LANG_YOU_CHANGE_RUNIC_POWER = 173, + LANG_YOURS_RUNIC_POWER_CHANGED = 174, + // Room for more level 1 175-199 not used // level 2 chat LANG_NO_SELECTION = 200, @@ -322,6 +324,8 @@ enum TrinityStrings LANG_CREATURE_NOT_FOLLOW_YOU_NOW = 342, LANG_CREATURE_NON_TAMEABLE = 343, LANG_YOU_ALREADY_HAVE_PET = 344, + LANG_CUSTOMIZE_PLAYER = 345, + LANG_CUSTOMIZE_PLAYER_GUID = 346, // Room for more level 2 345-399 not used // level 3 chat @@ -636,12 +640,44 @@ enum TrinityStrings LANG_BG_QUEUE_ANNOUNCE_SELF = 711, LANG_BG_QUEUE_ANNOUNCE_WORLD = 712, - - LANG_YOUR_ARENA_LEVEL_REQ_ERROR = 713, -// LANG_HIS_ARENA_LEVEL_REQ_ERROR = 714, an opcode exists for this +// = 714, not used LANG_YOUR_BG_LEVEL_REQ_ERROR = 715, + // LANG_YOUR_ARENA_TEAM_FULL = 716, an opcode exists for this + LANG_BG_STARTED_ANNOUNCE_WORLD = 717, + LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN= 718, + LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT= 719, + + LANG_BG_GROUP_TOO_LARGE = 720, // "Your group is too large for this battleground. Please regroup to join." + LANG_ARENA_GROUP_TOO_LARGE = 721, // "Your group is too large for this arena. Please regroup to join." + LANG_ARENA_YOUR_TEAM_ONLY = 722, // "Your group has members not in your arena team. Please regroup to join." + LANG_ARENA_NOT_ENOUGH_PLAYERS = 723, // "Your group does not have enough players to join this match." + LANG_ARENA_GOLD_WINS = 724, // "The Gold Team wins!" + LANG_ARENA_GREEN_WINS = 725, // "The Green Team wins!" + LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 726, // The battleground will end soon, because there aren't enough players. Get more ppl or win already! + LANG_BG_GROUP_OFFLINE_MEMBER = 727, // "Your group has an offline member. Please remove him before joining." + LANG_BG_GROUP_MIXED_FACTION = 728, // "Your group has players from the opposing faction. You can't join the battleground as a group." + LANG_BG_GROUP_MIXED_LEVELS = 729, // "Your group has players from different battleground brakets. You can't join as group." + LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 730, // "Someone in your party is already in this battleground queue. (S)he must leave it before joining as group." + LANG_BG_GROUP_MEMBER_DESERTER = 731, // "Someone in your party is Deserter. You can't join as group." + LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 732, // "Someone in your party is already in three battleground queues. You cannot join as group." + + LANG_CANNOT_TELE_TO_BG = 733, // "You cannot teleport to a battleground or arena map." + LANG_CANNOT_SUMMON_TO_BG = 734, // "You cannot summon players to a battleground or arena map." + LANG_CANNOT_GO_TO_BG_GM = 735, // "You must be in GM mode to teleport to a player in a battleground." + LANG_CANNOT_GO_TO_BG_FROM_BG = 736, // "You cannot teleport to a battleground from another battleground. Please leave the current battleground first." + LANG_DEBUG_ARENA_ON = 737, + LANG_DEBUG_ARENA_OFF = 738, + LANG_DEBUG_BG_ON = 739, + LANG_DEBUG_BG_OFF = 740, + LANG_DIST_ARENA_POINTS_START = 741, + LANG_DIST_ARENA_POINTS_ONLINE_START = 742, + LANG_DIST_ARENA_POINTS_ONLINE_END = 743, + LANG_DIST_ARENA_POINTS_TEAM_START = 744, + LANG_DIST_ARENA_POINTS_TEAM_END = 745, + LANG_DIST_ARENA_POINTS_END = 746, + // Room for batleground/arena strings 747-799 not used LANG_BG_AV_ALLY = 717, LANG_BG_AV_HORDE = 718, @@ -687,25 +723,6 @@ enum TrinityStrings LANG_AUTO_ANN = 786, LANG_ANNOUNCE_COLOR = 787, - LANG_BG_GROUP_TOO_LARGE = 1122, // "Your group is too large for this battleground. Please regroup to join." - LANG_ARENA_GROUP_TOO_LARGE = 1123, // "Your group is too large for this arena. Please regroup to join." - LANG_ARENA_YOUR_TEAM_ONLY = 1124, // "Your group has members not in your arena team. Please regroup to join." - LANG_ARENA_NOT_ENOUGH_PLAYERS = 1125, // "Your group does not have enough players to join this match." - LANG_ARENA_GOLD_WINS = 1126, // "The Gold Team wins!" - LANG_ARENA_GREEN_WINS = 1127, // "The Green Team wins!" - LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 1128, // The battleground will end soon, because there aren't enough players. Get more ppl or win already! - LANG_BG_GROUP_OFFLINE_MEMBER = 1129, // "Your group has an offline member. Please remove him before joining." - LANG_BG_GROUP_MIXED_FACTION = 1130, // "Your group has players from the opposing faction. You can't join the battleground as a group." - LANG_BG_GROUP_MIXED_LEVELS = 1131, // "Your group has players from different battleground brakets. You can't join as group." - LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 1132, // "Someone in your party is already in this battleground queue. (S)he must leave it before joining as group." - LANG_BG_GROUP_MEMBER_DESERTER = 1133, // "Someone in your party is Deserter. You can't join as group." - LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 1134, // "Someone in your party is already in three battleground queues. You cannot join as group." - - LANG_CANNOT_TELE_TO_BG = 1135, // "You cannot teleport to a battleground or arena map." - LANG_CANNOT_SUMMON_TO_BG = 1136, // "You cannot summon players to a battleground or arena map." - LANG_CANNOT_GO_TO_BG_GM = 1137, // "You must be in GM mode to teleport to a player in a battleground." - LANG_CANNOT_GO_TO_BG_FROM_BG = 1138, // "You cannot teleport to a battleground from another battleground. Please leave the current battleground first." - // in game strings LANG_PET_INVALID_NAME = 800, LANG_NOT_ENOUGH_GOLD = 801, @@ -757,6 +774,29 @@ enum TrinityStrings LANG_MUST_MALE_OR_FEMALE = 1119, LANG_YOU_CHANGE_GENDER = 1120, LANG_YOUR_GENDER_CHANGED = 1121, + LANG_SKILL_VALUES = 1122, + // Room for more level 3 1123-1199 not used + + /*LANG_BG_GROUP_TOO_LARGE = 1122, // "Your group is too large for this battleground. Please regroup to join." + LANG_ARENA_GROUP_TOO_LARGE = 1123, // "Your group is too large for this arena. Please regroup to join." + LANG_ARENA_YOUR_TEAM_ONLY = 1124, // "Your group has members not in your arena team. Please regroup to join." + LANG_ARENA_NOT_ENOUGH_PLAYERS = 1125, // "Your group does not have enough players to join this match." + LANG_ARENA_GOLD_WINS = 1126, // "The Gold Team wins!" + LANG_ARENA_GREEN_WINS = 1127, // "The Green Team wins!" + LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 1128, // The battleground will end soon, because there aren't enough players. Get more ppl or win already! + LANG_BG_GROUP_OFFLINE_MEMBER = 1129, // "Your group has an offline member. Please remove him before joining." + LANG_BG_GROUP_MIXED_FACTION = 1130, // "Your group has players from the opposing faction. You can't join the battleground as a group." + LANG_BG_GROUP_MIXED_LEVELS = 1131, // "Your group has players from different battleground brakets. You can't join as group." + LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 1132, // "Someone in your party is already in this battleground queue. (S)he must leave it before joining as group." + LANG_BG_GROUP_MEMBER_DESERTER = 1133, // "Someone in your party is Deserter. You can't join as group." + LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 1134, // "Someone in your party is already in three battleground queues. You cannot join as group." + + LANG_CANNOT_TELE_TO_BG = 1135, // "You cannot teleport to a battleground or arena map." + LANG_CANNOT_SUMMON_TO_BG = 1136, // "You cannot summon players to a battleground or arena map." + LANG_CANNOT_GO_TO_BG_GM = 1137, // "You must be in GM mode to teleport to a player in a battleground." + LANG_CANNOT_GO_TO_BG_FROM_BG = 1138, // "You cannot teleport to a battleground from another battleground. Please leave the current battleground first."*/ + + // FREE IDS 1200-9999 // Ticket Strings 2000-2029 LANG_COMMAND_TICKETNEW = 2000, diff --git a/src/game/Level0.cpp b/src/game/Level0.cpp index bd40ee431ac..d02671c724e 100644 --- a/src/game/Level0.cpp +++ b/src/game/Level0.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -172,7 +172,7 @@ bool ChatHandler::HandleGMListIngameCommand(const char* /*args*/) first = false; } - SendSysMessage(itr->second->GetName()); + SendSysMessage(GetNameLink(itr->second).c_str()); } } diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 5ee72a786d9..8bf4e52a2d4 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -115,6 +115,10 @@ bool ChatHandler::HandleNpcWhisperCommand(const char* args) uint64 receiver_guid= atol(receiver_str); + // check online security + if (HasLowerSecurity(objmgr.GetPlayer(receiver_guid), 0)) + return false; + pCreature->Whisper(text,receiver_guid); return true; @@ -125,8 +129,7 @@ bool ChatHandler::HandleNameAnnounceCommand(const char* args) WorldPacket data; if(!*args) return false; - //char str[1024]; - //sprintf(str, GetTrinityString(LANG_ANNOUNCE_COLOR), m_session->GetPlayer()->GetName(), args); + sWorld.SendWorldText(LANG_ANNOUNCE_COLOR, m_session->GetPlayer()->GetName(), args); return true; } @@ -650,14 +653,16 @@ bool ChatHandler::HandleVisibleCommand(const char* args) return false; } + + bool ChatHandler::HandleGPSCommand(const char* args) { WorldObject *obj = NULL; if (*args) { - std::string name = args; - if(normalizePlayerName(name)) - obj = objmgr.GetPlayer(name.c_str()); + uint64 guid = extractGuidFromLink((char*)args); + if(guid) + obj = (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*m_session->GetPlayer(),guid,TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); if(!obj) { @@ -708,18 +713,20 @@ bool ChatHandler::HandleGPSCommand(const char* args) obj->GetMapId(), (mapEntry ? mapEntry->name[m_session->GetSessionDbcLocale()] : "<unknown>" ), zone_id, (zoneEntry ? zoneEntry->area_name[m_session->GetSessionDbcLocale()] : "<unknown>" ), area_id, (areaEntry ? areaEntry->area_name[m_session->GetSessionDbcLocale()] : "<unknown>" ), + obj->GetPhaseMask(), obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(), cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(), zone_x, zone_y, ground_z, floor_z, have_map, have_vmap ); sLog.outDebug("Player %s GPS call for %s '%s' (%s: %u):", - GetName(), + m_session ? GetNameLink().c_str() : GetMangosString(LANG_CONSOLE_COMMAND), (obj->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), obj->GetName(), (obj->GetTypeId() == TYPEID_PLAYER ? "GUID" : "Entry"), (obj->GetTypeId() == TYPEID_PLAYER ? obj->GetGUIDLow(): obj->GetEntry()) ); sLog.outDebug(GetTrinityString(LANG_MAP_POSITION), obj->GetMapId(), (mapEntry ? mapEntry->name[sWorld.GetDefaultDbcLocale()] : "<unknown>" ), zone_id, (zoneEntry ? zoneEntry->area_name[sWorld.GetDefaultDbcLocale()] : "<unknown>" ), area_id, (areaEntry ? areaEntry->area_name[sWorld.GetDefaultDbcLocale()] : "<unknown>" ), + obj->GetPhaseMask(), obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), obj->GetOrientation(), cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), obj->GetInstanceId(), zone_x, zone_y, ground_z, floor_z, have_map, have_vmap ); @@ -733,9 +740,8 @@ bool ChatHandler::HandleNamegoCommand(const char* args) if(!*args) return false; - std::string name = args; - - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -745,9 +751,14 @@ bool ChatHandler::HandleNamegoCommand(const char* args) Player *chr = objmgr.GetPlayer(name.c_str()); if (chr) { + std::string nameLink = playerLink(name); + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + if(chr->IsBeingTeleported()==true) { - PSendSysMessage(LANG_IS_TELEPORTED, chr->GetName()); + PSendSysMessage(LANG_IS_TELEPORTED, nameLink.c_str()); SetSentErrorMessage(true); return false; } @@ -756,10 +767,25 @@ bool ChatHandler::HandleNamegoCommand(const char* args) if(pMap->IsBattleGroundOrArena()) { - // cannot summon to bg - PSendSysMessage(LANG_CANNOT_SUMMON_TO_BG,chr->GetName()); - SetSentErrorMessage(true); - return false; + // only allow if gm mode is on + if (!chr->isGameMaster()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + // if both players are in different bgs + else if (chr->GetBattleGroundId() && m_session->GetPlayer()->GetBattleGroundId() != chr->GetBattleGroundId()) + { + PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + // all's well, set bg id + // when porting out from the bg, it will be reset to 0 + chr->SetBattleGroundId(m_session->GetPlayer()->GetBattleGroundId()); + // remember current position as entry point for return at bg end teleportation + chr->SetBattleGroundEntryPoint(chr->GetMapId(),chr->GetPositionX(),chr->GetPositionY(),chr->GetPositionZ(),chr->GetOrientation()); } else if(pMap->IsDungeon()) { @@ -767,7 +793,7 @@ bool ChatHandler::HandleNamegoCommand(const char* args) if( cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId() ) { // cannot summon from instance to instance - PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,chr->GetName()); + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str()); SetSentErrorMessage(true); return false; } @@ -778,15 +804,15 @@ bool ChatHandler::HandleNamegoCommand(const char* args) (m_session->GetPlayer()->GetGroup()->GetLeaderGUID() != m_session->GetPlayer()->GetGUID()) ) // the last check is a bit excessive, but let it be, just in case { - PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,chr->GetName()); + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,nameLink.c_str()); SetSentErrorMessage(true); return false; } } - PSendSysMessage(LANG_SUMMONING, chr->GetName(),""); + PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),""); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_SUMMONED_BY, GetName()); + ChatHandler(chr).PSendSysMessage(LANG_SUMMONED_BY, nameLink.c_str()); // stop flight if need if(chr->isInFlight()) @@ -805,7 +831,13 @@ bool ChatHandler::HandleNamegoCommand(const char* args) } else if (uint64 guid = objmgr.GetPlayerGUIDByName(name)) { - PSendSysMessage(LANG_SUMMONING, name.c_str(),GetTrinityString(LANG_OFFLINE)); + // check offline security + if (HasLowerSecurity(NULL, guid)) + return false; + + std::string nameLink = playerLink(name); + + PSendSysMessage(LANG_SUMMONING, nameLink.c_str(),GetMangosString(LANG_OFFLINE)); // in point where GM stay Player::SavePositionInDB(m_session->GetPlayer()->GetMapId(), @@ -833,9 +865,8 @@ bool ChatHandler::HandleGonameCommand(const char* args) Player* _player = m_session->GetPlayer(); - std::string name = args; - - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -845,28 +876,36 @@ bool ChatHandler::HandleGonameCommand(const char* args) Player *chr = objmgr.GetPlayer(name.c_str()); if (chr) { + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = playerLink(name); + Map* cMap = chr->GetMap(); if(cMap->IsBattleGroundOrArena()) { // only allow if gm mode is on if (!_player->isGameMaster()) { - PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chr->GetName()); + PSendSysMessage(LANG_CANNOT_GO_TO_BG_GM,chrNameLink.c_str()); SetSentErrorMessage(true); return false; } - // if already in a bg, don't let port to other - else if (_player->GetBattleGroundId()) + // if both players are in different bgs + else if (_player->GetBattleGroundId() && _player->GetBattleGroundId() != chr->GetBattleGroundId()) { - PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chr->GetName()); + PSendSysMessage(LANG_CANNOT_GO_TO_BG_FROM_BG,chrNameLink.c_str()); SetSentErrorMessage(true); return false; } // all's well, set bg id // when porting out from the bg, it will be reset to 0 _player->SetBattleGroundId(chr->GetBattleGroundId()); + // remember current position as entry point for return at bg end teleportation + _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); } - else if(cMap->IsDungeon()) + else if(cMap->IsDungeon() && cMap->Instanceable()) { Map* pMap = MapManager::Instance().GetMap(_player->GetMapId(),_player); @@ -878,7 +917,7 @@ bool ChatHandler::HandleGonameCommand(const char* args) // we are in group, we can go only if we are in the player group if (_player->GetGroup() != chr->GetGroup()) { - PSendSysMessage(LANG_CANNOT_GO_TO_INST_PARTY,chr->GetName()); + PSendSysMessage(LANG_CANNOT_GO_TO_INST_PARTY,chrNameLink.c_str()); SetSentErrorMessage(true); return false; } @@ -888,7 +927,7 @@ bool ChatHandler::HandleGonameCommand(const char* args) // we are not in group, let's verify our GM mode if (!_player->isGameMaster()) { - PSendSysMessage(LANG_CANNOT_GO_TO_INST_GM,chr->GetName()); + PSendSysMessage(LANG_CANNOT_GO_TO_INST_GM,chrNameLink.c_str()); SetSentErrorMessage(true); return false; } @@ -912,10 +951,9 @@ bool ChatHandler::HandleGonameCommand(const char* args) _player->SetDifficulty(chr->GetDifficulty()); } - PSendSysMessage(LANG_APPEARING_AT, chr->GetName()); - + PSendSysMessage(LANG_APPEARING_AT, chrNameLink.c_str()); if (_player->IsVisibleGloballyFor(chr)) - ChatHandler(chr).PSendSysMessage(LANG_APPEARING_TO, _player->GetName()); + ChatHandler(chr).PSendSysMessage(LANG_APPEARING_TO, GetNameLink().c_str()); // stop flight if need if(_player->isInFlight()) @@ -938,7 +976,13 @@ bool ChatHandler::HandleGonameCommand(const char* args) if (uint64 guid = objmgr.GetPlayerGUIDByName(name)) { - PSendSysMessage(LANG_APPEARING_AT, name.c_str()); + // check offline security + if (HasLowerSecurity(NULL, guid)) + return false; + + std::string nameLink = playerLink(name); + + PSendSysMessage(LANG_APPEARING_AT, nameLink.c_str()); // to point where player stay (if loaded) float x,y,z,o; @@ -977,12 +1021,15 @@ bool ChatHandler::HandleRecallCommand(const char* args) chr = getSelectedPlayer(); if(!chr) chr = m_session->GetPlayer(); + + // check online security + else if (HasLowerSecurity(chr, 0)) + return false; } else { - std::string name = args; - - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -997,11 +1044,15 @@ bool ChatHandler::HandleRecallCommand(const char* args) SetSentErrorMessage(true); return false; } + + // check online security + if (HasLowerSecurity(chr, 0)) + return false; } if(chr->IsBeingTeleported()) { - PSendSysMessage(LANG_IS_TELEPORTED, chr->GetName()); + PSendSysMessage(LANG_IS_TELEPORTED, GetNameLink(chr).c_str()); SetSentErrorMessage(true); return false; } @@ -1035,6 +1086,10 @@ bool ChatHandler::HandleModifyKnownTitlesCommand(const char* args) return false; } + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + uint64 titles2 = titles; for(int i=1; i < sCharTitlesStore.GetNumRows(); ++i) @@ -1084,9 +1139,13 @@ bool ChatHandler::HandleModifyHPCommand(const char* args) return false; } - PSendSysMessage(LANG_YOU_CHANGE_HP, chr->GetName(), hp, hpm); + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_HP, GetNameLink(chr).c_str(), hp, hpm); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, GetName(), hp, hpm); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_HP_CHANGED, GetNameLink().c_str(), hp, hpm); chr->SetMaxHealth( hpm ); chr->SetHealth( hp ); @@ -1128,9 +1187,13 @@ bool ChatHandler::HandleModifyManaCommand(const char* args) return false; } - PSendSysMessage(LANG_YOU_CHANGE_MANA, chr->GetName(), mana, manam); + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_MANA, GetNameLink(chr).c_str(), mana, manam); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, GetName(), mana, manam); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MANA_CHANGED, GetNameLink().c_str(), mana, manam); chr->SetMaxPower(POWER_MANA,manam ); chr->SetPower(POWER_MANA, mana ); @@ -1173,9 +1236,13 @@ bool ChatHandler::HandleModifyEnergyCommand(const char* args) return false; } - PSendSysMessage(LANG_YOU_CHANGE_ENERGY, chr->GetName(), energy/10, energym/10); + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_ENERGY, GetNameLink(chr).c_str(), energy/10, energym/10); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, GetName(), energy/10, energym/10); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, GetNameLink().c_str(), energy/10, energym/10); chr->SetMaxPower(POWER_ENERGY,energym ); chr->SetPower(POWER_ENERGY, energy ); @@ -1220,9 +1287,13 @@ bool ChatHandler::HandleModifyRageCommand(const char* args) return false; } - PSendSysMessage(LANG_YOU_CHANGE_RAGE, chr->GetName(), rage/10, ragem/10); + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_RAGE, GetNameLink(chr).c_str(), rage/10, ragem/10); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, GetName(), rage/10, ragem/10); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, GetNameLink().c_str(), rage/10, ragem/10); chr->SetMaxPower(POWER_RAGE,ragem ); chr->SetPower(POWER_RAGE, rage ); @@ -1230,6 +1301,40 @@ bool ChatHandler::HandleModifyRageCommand(const char* args) return true; } +// Edit Player Runic Power +bool ChatHandler::HandleModifyRunicPowerCommand(const char* args) +{ + if(!*args) + return false; + + int32 rune = atoi((char*)args)*10; + int32 runem = atoi((char*)args)*10; + + if (rune <= 0 || runem <= 0 || runem < rune) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Player *chr = getSelectedPlayer(); + if (chr == NULL) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + PSendSysMessage(LANG_YOU_CHANGE_RUNIC_POWER, GetNameLink(chr).c_str(), rune/10, runem/10); + if (needReportToTarget(chr)) + ChatHandler(chr).PSendSysMessage(LANG_YOURS_RUNIC_POWER_CHANGED, GetNameLink().c_str(), rune/10, runem/10); + + chr->SetMaxPower(POWER_RUNIC_POWER,runem ); + chr->SetPower(POWER_RUNIC_POWER, rune ); + + return true; +} + //Edit Player Faction bool ChatHandler::HandleModifyFactionCommand(const char* args) { @@ -1344,9 +1449,13 @@ bool ChatHandler::HandleModifySpellCommand(const char* args) return false; } - PSendSysMessage(LANG_YOU_CHANGE_SPELLFLATID, spellflatid, val, mark, chr->GetName()); + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_SPELLFLATID, spellflatid, val, mark, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, GetName(), spellflatid, val, mark); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPELLFLATID_CHANGED, GetNameLink().c_str(), spellflatid, val, mark); WorldPacket data(SMSG_SET_FLAT_SPELL_MODIFIER, (1+1+2+2)); data << uint8(spellflatid); @@ -1374,6 +1483,11 @@ bool ChatHandler::HandleModifyTalentCommand (const char* args) SetSentErrorMessage(true); return false; } + + // check online security + if (HasLowerSecurity(player, 0)) + return false; + player->SetFreeTalentPoints(tp); return true; } @@ -1398,21 +1512,25 @@ bool ChatHandler::HandleTaxiCheatCommand(const char* args) chr=m_session->GetPlayer(); } + // check online security + else if (HasLowerSecurity(chr, 0)) + return false; + if (argstr == "on") { chr->SetTaxiCheater(true); - PSendSysMessage(LANG_YOU_GIVE_TAXIS, chr->GetName()); + PSendSysMessage(LANG_YOU_GIVE_TAXIS, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, GetName()); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, GetNameLink().c_str()); return true; } if (argstr == "off") { chr->SetTaxiCheater(false); - PSendSysMessage(LANG_YOU_REMOVE_TAXIS, chr->GetName()); + PSendSysMessage(LANG_YOU_REMOVE_TAXIS, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, GetName()); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, GetNameLink().c_str()); return true; } @@ -1445,16 +1563,22 @@ bool ChatHandler::HandleModifyASpeedCommand(const char* args) return false; } + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + if(chr->isInFlight()) { - PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); SetSentErrorMessage(true); return false; } - PSendSysMessage(LANG_YOU_CHANGE_ASPEED, ASpeed, chr->GetName()); + PSendSysMessage(LANG_YOU_CHANGE_ASPEED, ASpeed, chrNameLink.c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, GetName(), ASpeed); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, GetNameLink().c_str(), ASpeed); chr->SetSpeed(MOVE_WALK, ASpeed,true); chr->SetSpeed(MOVE_RUN, ASpeed,true); @@ -1487,16 +1611,22 @@ bool ChatHandler::HandleModifySpeedCommand(const char* args) return false; } + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + if(chr->isInFlight()) { - PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); SetSentErrorMessage(true); return false; } - PSendSysMessage(LANG_YOU_CHANGE_SPEED, Speed, chr->GetName()); + PSendSysMessage(LANG_YOU_CHANGE_SPEED, Speed, chrNameLink.c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, GetName(), Speed); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, GetNameLink().c_str(), Speed); chr->SetSpeed(MOVE_RUN,Speed,true); @@ -1526,16 +1656,22 @@ bool ChatHandler::HandleModifySwimCommand(const char* args) return false; } + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + if(chr->isInFlight()) { - PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); SetSentErrorMessage(true); return false; } - PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, Swim, chr->GetName()); + PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, Swim, chrNameLink.c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, GetName(), Swim); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, GetNameLink().c_str(), Swim); chr->SetSpeed(MOVE_SWIM,Swim,true); @@ -1565,16 +1701,22 @@ bool ChatHandler::HandleModifyBWalkCommand(const char* args) return false; } + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = GetNameLink(chr); + if(chr->isInFlight()) { - PSendSysMessage(LANG_CHAR_IN_FLIGHT,chr->GetName()); + PSendSysMessage(LANG_CHAR_IN_FLIGHT,chrNameLink.c_str()); SetSentErrorMessage(true); return false; } - PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, BSpeed, chr->GetName()); + PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, BSpeed, chrNameLink.c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetName(), BSpeed); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetNameLink().c_str(), BSpeed); chr->SetSpeed(MOVE_RUN_BACK,BSpeed,true); @@ -1604,9 +1746,13 @@ bool ChatHandler::HandleModifyFlyCommand(const char* args) return false; } - PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, FSpeed, chr->GetName()); + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, FSpeed, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetName(), FSpeed); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetNameLink().c_str(), FSpeed); chr->SetSpeed(MOVE_FLIGHT,FSpeed,true); @@ -1635,9 +1781,13 @@ bool ChatHandler::HandleModifyScaleCommand(const char* args) return false; } - PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, chr->GetName()); + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_CHANGE_SIZE, Scale, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, GetName(), Scale); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, GetNameLink().c_str(), Scale); chr->SetFloatValue(OBJECT_FIELD_SCALE_X, Scale); @@ -1878,9 +2028,13 @@ bool ChatHandler::HandleModifyMountCommand(const char* args) return false; } - PSendSysMessage(LANG_YOU_GIVE_MOUNT, chr->GetName()); + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + PSendSysMessage(LANG_YOU_GIVE_MOUNT, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_MOUNT_GIVED, GetName()); + ChatHandler(chr).PSendSysMessage(LANG_MOUNT_GIVED, GetNameLink().c_str()); chr->SetUInt32Value( UNIT_FIELD_FLAGS , 0x001000 ); chr->Mount(mId); @@ -1915,6 +2069,10 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args) return false; } + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + int32 addmoney = atoi((char*)args); uint32 moneyuser = chr->GetMoney(); @@ -1926,25 +2084,25 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args) sLog.outDetail(GetTrinityString(LANG_CURRENT_MONEY), moneyuser, addmoney, newmoney); if(newmoney <= 0 ) { - PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, chr->GetName()); + PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, GetName()); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, GetNameLink().c_str()); chr->SetMoney(0); } else { - PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), chr->GetName()); + PSendSysMessage(LANG_YOU_TAKE_MONEY, abs(addmoney), GetNameLink(chr).c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetName(), abs(addmoney)); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_TAKEN, GetNameLink().c_str(), abs(addmoney)); chr->SetMoney( newmoney ); } } else { - PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, chr->GetName()); + PSendSysMessage(LANG_YOU_GIVE_MONEY, addmoney, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetName(), addmoney); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_MONEY_GIVEN, GetNameLink().c_str(), addmoney); chr->ModifyMoney( addmoney ); } @@ -1953,20 +2111,24 @@ bool ChatHandler::HandleModifyMoneyCommand(const char* args) return true; } -//Edit Player field +//Edit Unit field bool ChatHandler::HandleModifyBitCommand(const char* args) { if( !*args ) return false; - Player *chr = getSelectedPlayer(); - if (chr == NULL) + Unit *unit = getSelectedUnit(); + if (!unit) { SendSysMessage(LANG_NO_CHAR_SELECTED); SetSentErrorMessage(true); return false; } + // check online security + if (unit->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player *)unit, 0)) + return false; + char* pField = strtok((char*)args, " "); if (!pField) return false; @@ -1978,13 +2140,12 @@ bool ChatHandler::HandleModifyBitCommand(const char* args) uint16 field = atoi(pField); uint32 bit = atoi(pBit); - if (field < 1 || field >= PLAYER_END) + if (field < OBJECT_END || field >= unit->GetValuesCount()) { SendSysMessage(LANG_BAD_VALUE); SetSentErrorMessage(true); return false; } - if (bit < 1 || bit > 32) { SendSysMessage(LANG_BAD_VALUE); @@ -1992,17 +2153,16 @@ bool ChatHandler::HandleModifyBitCommand(const char* args) return false; } - if ( chr->HasFlag( field, (1<<(bit-1)) ) ) + if ( unit->HasFlag( field, (1<<(bit-1)) ) ) { - chr->RemoveFlag( field, (1<<(bit-1)) ); + unit->RemoveFlag( field, (1<<(bit-1)) ); PSendSysMessage(LANG_REMOVE_BIT, bit, field); } else { - chr->SetFlag( field, (1<<(bit-1)) ); + unit->SetFlag( field, (1<<(bit-1)) ); PSendSysMessage(LANG_SET_BIT, bit, field); } - return true; } @@ -2019,11 +2179,15 @@ bool ChatHandler::HandleModifyHonorCommand (const char* args) return false; } + // check online security + if (HasLowerSecurity(target, 0)) + return false; + int32 amount = (uint32)atoi(args); target->ModifyHonorPoints(amount); - PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, target->GetName(), target->GetHonorPoints()); + PSendSysMessage(LANG_COMMAND_MODIFY_HONOR, GetNameLink(target).c_str(), target->GetHonorPoints()); return true; } @@ -2126,8 +2290,10 @@ bool ChatHandler::HandleLookupAreaCommand(const char* args) } } } + if (counter == 0) // if counter == 0 then we found nth SendSysMessage (LANG_COMMAND_NOAREAFOUND); + return true; } @@ -2254,9 +2420,13 @@ bool ChatHandler::HandleSendMailCommand(const char* args) // format: name "subject text" "mail text" - char* pName = strtok((char*)args, " "); - if(!pName) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); return false; + } char* tail1 = strtok(NULL, ""); if(!tail1) @@ -2294,18 +2464,10 @@ bool ChatHandler::HandleSendMailCommand(const char* args) if (!msgText) return false; - // pName, msgSubject, msgText isn't NUL after prev. check - std::string name = pName; + // msgSubject, msgText isn't NUL after prev. check std::string subject = msgSubject; std::string text = msgText; - if(!normalizePlayerName(name)) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - uint64 receiver_guid = objmgr.GetPlayerGUIDByName(name); if(!receiver_guid) { @@ -2314,7 +2476,6 @@ bool ChatHandler::HandleSendMailCommand(const char* args) return false; } - uint32 mailId = objmgr.GenerateMailID(); // from console show not existed sender uint32 sender_guidlo = m_session ? m_session->GetPlayer()->GetGUIDLow() : 0; @@ -2326,7 +2487,8 @@ bool ChatHandler::HandleSendMailCommand(const char* args) WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, NULL, 0, 0, MAIL_CHECK_MASK_NONE); - PSendSysMessage(LANG_MAIL_SENT, name.c_str()); + std::string nameLink = playerLink(name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); return true; } @@ -2336,14 +2498,8 @@ bool ChatHandler::HandleNameTeleCommand(const char * args) if(!*args) return false; - char* pName = strtok((char*)args, " "); - - if(!pName) - return false; - - std::string name = pName; - - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -2374,17 +2530,22 @@ bool ChatHandler::HandleNameTeleCommand(const char * args) Player *chr = objmgr.GetPlayer(name.c_str()); if (chr) { + // check online security + if (HasLowerSecurity(chr, 0)) + return false; + + std::string chrNameLink = playerLink(name); if(chr->IsBeingTeleported()==true) { - PSendSysMessage(LANG_IS_TELEPORTED, chr->GetName()); + PSendSysMessage(LANG_IS_TELEPORTED, chrNameLink.c_str()); SetSentErrorMessage(true); return false; } - PSendSysMessage(LANG_TELEPORTING_TO, chr->GetName(),"", tele->name.c_str()); + PSendSysMessage(LANG_TELEPORTING_TO, chrNameLink.c_str(),"", tele->name.c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetName()); + ChatHandler(chr).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetNameLink().c_str()); // stop flight if need if(chr->isInFlight()) @@ -2398,10 +2559,17 @@ bool ChatHandler::HandleNameTeleCommand(const char * args) chr->TeleportTo(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation); } - else if (uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str())) + else if (uint64 guid = objmgr.GetPlayerGUIDByName(name)) { - PSendSysMessage(LANG_TELEPORTING_TO, name.c_str(), GetTrinityString(LANG_OFFLINE), tele->name.c_str()); - Player::SavePositionInDB(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation,MapManager::Instance().GetZoneId(tele->mapId,tele->position_x,tele->position_y),guid); + // check offline security + if (HasLowerSecurity(NULL, guid)) + return false; + + std::string nameLink = playerLink(name); + + PSendSysMessage(LANG_TELEPORTING_TO, nameLink.c_str(), GetMangosString(LANG_OFFLINE), tele->name.c_str()); + Player::SavePositionInDB(tele->mapId,tele->position_x,tele->position_y,tele->position_z,tele->orientation, + MapManager::Instance().GetZoneId(tele->mapId,tele->position_x,tele->position_y,tele->position_z),guid); } else PSendSysMessage(LANG_NO_PLAYER, name.c_str()); @@ -2423,6 +2591,10 @@ bool ChatHandler::HandleGroupTeleCommand(const char * args) return false; } + // check online security + if (HasLowerSecurity(player, 0)) + return false; + // id, or string, or [name] Shift-click form |color|Htele:id|h[name]|h|r GameTele const* tele = extractGameTeleFromLink((char*)args); if(!tele) @@ -2439,10 +2611,13 @@ bool ChatHandler::HandleGroupTeleCommand(const char * args) SetSentErrorMessage(true); return false; } + + std::string nameLink = GetNameLink(player); + Group *grp = player->GetGroup(); if(!grp) { - PSendSysMessage(LANG_NOT_IN_GROUP,player->GetName()); + PSendSysMessage(LANG_NOT_IN_GROUP,nameLink.c_str()); SetSentErrorMessage(true); return false; } @@ -2454,15 +2629,21 @@ bool ChatHandler::HandleGroupTeleCommand(const char * args) if(!pl || !pl->GetSession() ) continue; + // check online security + if (HasLowerSecurity(pl, 0)) + return false; + + std::string plNameLink = GetNameLink(pl); + if(pl->IsBeingTeleported()) { - PSendSysMessage(LANG_IS_TELEPORTED, pl->GetName()); + PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); continue; } - PSendSysMessage(LANG_TELEPORTING_TO, pl->GetName(),"", tele->name.c_str()); + PSendSysMessage(LANG_TELEPORTING_TO, plNameLink.c_str(),"", tele->name.c_str()); if (needReportToTarget(pl)) - ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, GetName()); + ChatHandler(pl).PSendSysMessage(LANG_TELEPORTED_TO_BY, nameLink.c_str()); // stop flight if need if(pl->isInFlight()) @@ -2486,9 +2667,8 @@ bool ChatHandler::HandleGroupgoCommand(const char* args) if(!*args) return false; - std::string name = args; - - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -2503,16 +2683,22 @@ bool ChatHandler::HandleGroupgoCommand(const char* args) return false; } + // check online security + if (HasLowerSecurity(player, 0)) + return false; + Group *grp = player->GetGroup(); + std::string nameLink = playerLink(name); + if(!grp) { - PSendSysMessage(LANG_NOT_IN_GROUP,player->GetName()); + PSendSysMessage(LANG_NOT_IN_GROUP,nameLink.c_str()); SetSentErrorMessage(true); return false; } - Map* gmMap = MapManager::Instance().GetMap(m_session->GetPlayer()->GetMapId(),m_session->GetPlayer()); + Map* gmMap = m_session->GetPlayer()->GetMap(); bool to_instance = gmMap->Instanceable(); // we are in instance, and can summon only player in our group with us as lead @@ -2533,29 +2719,35 @@ bool ChatHandler::HandleGroupgoCommand(const char* args) if(!pl || pl==m_session->GetPlayer() || !pl->GetSession() ) continue; + // check online security + if (HasLowerSecurity(pl, 0)) + return false; + + std::string plNameLink = playerLink(name); + if(pl->IsBeingTeleported()==true) { - PSendSysMessage(LANG_IS_TELEPORTED, pl->GetName()); + PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); SetSentErrorMessage(true); return false; } if (to_instance) { - Map* plMap = MapManager::Instance().GetMap(pl->GetMapId(),pl); + Map* plMap = pl->GetMap(); if ( plMap->Instanceable() && plMap->GetInstanceId() != gmMap->GetInstanceId() ) { // cannot summon from instance to instance - PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,pl->GetName()); + PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST,plNameLink.c_str()); SetSentErrorMessage(true); return false; } } - PSendSysMessage(LANG_SUMMONING, pl->GetName(),""); + PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(),""); if (needReportToTarget(pl)) - ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, GetName()); + ChatHandler(pl).PSendSysMessage(LANG_SUMMONED_BY, nameLink.c_str()); // stop flight if need if(pl->isInFlight()) diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 2b996cfd0fb..8d560783d89 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,12 +10,12 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "Common.h" @@ -36,6 +36,7 @@ #include "GameEvent.h" #include "SpellMgr.h" #include "AccountMgr.h" +//#include "GMTicketMgr.h" #include "WaypointManager.h" #include "Util.h" #include <cctype> @@ -58,11 +59,13 @@ bool ChatHandler::HandleMuteCommand(const char* args) if (!*args) return false; - char *charname = strtok((char*)args, " "); - if (!charname) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); return false; - - std::string cname = charname; + } char *timetonotspeak = strtok(NULL, " "); if(!timetonotspeak) @@ -70,14 +73,7 @@ bool ChatHandler::HandleMuteCommand(const char* args) uint32 notspeaktime = (uint32) atoi(timetonotspeak); - if(!normalizePlayerName(cname)) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - - uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str()); + uint64 guid = objmgr.GetPlayerGUIDByName(name); if(!guid) { SendSysMessage(LANG_PLAYER_NOT_FOUND); @@ -87,27 +83,11 @@ bool ChatHandler::HandleMuteCommand(const char* args) Player *chr = objmgr.GetPlayer(guid); - // check security - uint32 account_id = 0; - uint32 security = 0; - - if (chr) - { - account_id = chr->GetSession()->GetAccountId(); - security = chr->GetSession()->GetSecurity(); - } - else - { - account_id = objmgr.GetPlayerAccountIdByGUID(guid); - security = accmgr.GetSecurity(account_id); - } - - if(m_session && security >= m_session->GetSecurity()) - { - SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); - SetSentErrorMessage(true); + // must have strong lesser security level + if(HasLowerSecurity (chr,guid,true)) return false; - } + + uint32 account_id = chr ? chr->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(guid); time_t mutetime = time(NULL) + notspeaktime*60; @@ -119,7 +99,9 @@ bool ChatHandler::HandleMuteCommand(const char* args) if(chr) ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_DISABLED, notspeaktime); - PSendSysMessage(LANG_YOU_DISABLE_CHAT, cname.c_str(), notspeaktime); + std::string nameLink = playerLink(name); + + PSendSysMessage(LANG_YOU_DISABLE_CHAT, nameLink.c_str(), notspeaktime); return true; } @@ -130,20 +112,15 @@ bool ChatHandler::HandleUnmuteCommand(const char* args) if (!*args) return false; - char *charname = strtok((char*)args, " "); - if (!charname) - return false; - - std::string cname = charname; - - if(!normalizePlayerName(cname)) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); return false; } - uint64 guid = objmgr.GetPlayerGUIDByName(cname.c_str()); + uint64 guid = objmgr.GetPlayerGUIDByName(name); if(!guid) { SendSysMessage(LANG_PLAYER_NOT_FOUND); @@ -153,27 +130,11 @@ bool ChatHandler::HandleUnmuteCommand(const char* args) Player *chr = objmgr.GetPlayer(guid); - // check security - uint32 account_id = 0; - uint32 security = 0; - - if (chr) - { - account_id = chr->GetSession()->GetAccountId(); - security = chr->GetSession()->GetSecurity(); - } - else - { - account_id = objmgr.GetPlayerAccountIdByGUID(guid); - security = accmgr.GetSecurity(account_id); - } - - if(m_session && security >= m_session->GetSecurity()) - { - SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); - SetSentErrorMessage(true); + // must have strong lesser security level + if(HasLowerSecurity (chr,guid,true)) return false; - } + + uint32 account_id = chr ? chr->GetSession()->GetAccountId() : objmgr.GetPlayerAccountIdByGUID(guid); if (chr) { @@ -192,7 +153,9 @@ bool ChatHandler::HandleUnmuteCommand(const char* args) if(chr) ChatHandler(chr).PSendSysMessage(LANG_YOUR_CHAT_ENABLED); - PSendSysMessage(LANG_YOU_ENABLE_CHAT, cname.c_str()); + std::string nameLink = playerLink(name); + + PSendSysMessage(LANG_YOU_ENABLE_CHAT, nameLink.c_str()); return true; } @@ -588,6 +551,7 @@ bool ChatHandler::HandleLookupFactionCommand(const char* args) repState = &repItr->second; } + int loc = m_session ? m_session->GetSessionDbcLocale() : sWorld.GetDefaultDbcLocale(); std::string name = factionEntry->name[loc]; if(name.empty()) @@ -668,6 +632,10 @@ bool ChatHandler::HandleModifyRepCommand(const char * args) return false; } + // check online security + if (HasLowerSecurity(target, 0)) + return false; + char* factionTxt = extractKeyFromLink((char*)args,"Hfaction"); if(!factionTxt) return false; @@ -745,11 +713,11 @@ bool ChatHandler::HandleModifyRepCommand(const char * args) } target->SetFactionReputation(factionEntry,amount); - PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, target->GetName(), target->GetReputation(factionId)); + PSendSysMessage(LANG_COMMAND_MODIFY_REP, factionEntry->name[m_session->GetSessionDbcLocale()], factionId, GetNameLink(target).c_str(), target->GetReputation(factionId)); return true; } -bool ChatHandler::HandleNameCommand(const char* args) +bool ChatHandler::HandleNameCommand(const char* /*args*/) { /* Temp. disabled if(!*args) @@ -882,8 +850,8 @@ bool ChatHandler::HandleNpcAddCommand(const char* args) { if(!*args) return false; - char* charID = strtok((char*)args, " "); - if (!charID) + char* charID = extractKeyFromLink((char*)args,"Hcreature_entry"); + if(!charID) return false; char* team = strtok(NULL, " "); @@ -901,7 +869,7 @@ bool ChatHandler::HandleNpcAddCommand(const char* args) Map *map = chr->GetMap(); Creature* pCreature = new Creature; - if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, (uint32)teamval)) + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, (uint32)teamval)) { delete pCreature; return false; @@ -916,7 +884,7 @@ bool ChatHandler::HandleNpcAddCommand(const char* args) return false; } - pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); uint32 db_guid = pCreature->GetDBTableGUIDLow(); @@ -949,7 +917,7 @@ bool ChatHandler::HandleNpcDeleteCommand(const char* args) else unit = getSelectedCreature(); - if(!unit || unit->isPet() || unit->isTotem()) + if(!unit || unit->isPet() || unit->isTotem() || unit->isVehicle()) { SendSysMessage(LANG_SELECT_CREATURE); SetSentErrorMessage(true); @@ -1056,14 +1024,14 @@ bool ChatHandler::HandleTurnObjectCommand(const char* args) float rot2 = sin(o/2); float rot3 = cos(o/2); - Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj); + Map* map = obj->GetMap(); map->Remove(obj,false); obj->Relocate(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), o); obj->SetFloatValue(GAMEOBJECT_FACING, o); - obj->SetFloatValue(GAMEOBJECT_ROTATION+2, rot2); - obj->SetFloatValue(GAMEOBJECT_ROTATION+3, rot3); + obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rot2); + obj->SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rot3); map->Add(obj); @@ -1140,7 +1108,7 @@ bool ChatHandler::HandleNpcMoveCommand(const char* args) const_cast<CreatureData*>(data)->posZ = z; const_cast<CreatureData*>(data)->orientation = o; } - MapManager::Instance().GetMap(pCreature->GetMapId(),pCreature)->CreatureRelocation(pCreature,x, y, z,o); + pCreature->GetMap()->CreatureRelocation(pCreature,x, y, z,o); pCreature->GetMotionMaster()->Initialize(); if(pCreature->isAlive()) // dead creature will reset movement generator at respawn { @@ -1187,7 +1155,7 @@ bool ChatHandler::HandleMoveObjectCommand(const char* args) { Player *chr = m_session->GetPlayer(); - Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj); + Map* map = obj->GetMap(); map->Remove(obj,false); obj->Relocate(chr->GetPositionX(), chr->GetPositionY(), chr->GetPositionZ(), obj->GetOrientation()); @@ -1213,7 +1181,7 @@ bool ChatHandler::HandleMoveObjectCommand(const char* args) return false; } - Map* map = MapManager::Instance().GetMap(obj->GetMapId(),obj); + Map* map = obj->GetMap(); map->Remove(obj,false); obj->Relocate(x, y, z, obj->GetOrientation()); @@ -1239,6 +1207,11 @@ bool ChatHandler::HandleDeMorphCommand(const char* /*args*/) if(!target) target = m_session->GetPlayer(); + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + target->DeMorph(); return true; @@ -1314,7 +1287,6 @@ bool ChatHandler::HandleDelVendorItemCommand(const char* args) } uint32 itemId = atol(pitem); - if(!objmgr.RemoveVendorItem(vendor->GetEntry(),itemId)) { PSendSysMessage(LANG_ITEM_NOT_IN_LIST,itemId); @@ -1629,6 +1601,10 @@ bool ChatHandler::HandleMorphCommand(const char* args) if(!target) target = m_session->GetPlayer(); + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + target->SetDisplayId(display_id); return true; @@ -1688,7 +1664,7 @@ bool ChatHandler::HandleKickPlayerCommand(const char *args) kicker = m_session->GetPlayer()->GetName(); if(!kickName) - { + { Player* player = getSelectedPlayer(); if(!player) { @@ -1704,14 +1680,16 @@ bool ChatHandler::HandleKickPlayerCommand(const char *args) return false; } + // check online security + if (HasLowerSecurity(player, 0)) + return false; + if(sWorld.getConfig(CONFIG_SHOW_KICK_IN_WORLD) == 1) { - sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, player->GetName(), kicker.c_str(), reason.c_str()); } else { - PSendSysMessage(LANG_COMMAND_KICKMESSAGE, player->GetName(), kicker.c_str(), reason.c_str()); } @@ -1719,8 +1697,8 @@ bool ChatHandler::HandleKickPlayerCommand(const char *args) } else { - std::string name = kickName; - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink((char*)kickName); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -1742,34 +1720,56 @@ bool ChatHandler::HandleKickPlayerCommand(const char *args) return false; } - if(m_session && player->GetSession()->GetSecurity() > m_session->GetSecurity()) + if(HasLowerSecurity(player, 0)) { SendSysMessage(LANG_YOURS_SECURITY_IS_LOW); //maybe replacement string for this later on SetSentErrorMessage(true); return false; } - if(sWorld.KickPlayer(name.c_str())) + std::string nameLink = playerLink(name); + + if(sWorld.KickPlayer(name)) { if(sWorld.getConfig(CONFIG_SHOW_KICK_IN_WORLD) == 1) { - - sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, name.c_str(), kicker.c_str(), reason.c_str()); + sWorld.SendWorldText(LANG_COMMAND_KICKMESSAGE, nameLink.c_str(), kicker.c_str(), reason.c_str()); } else { - PSendSysMessage(LANG_COMMAND_KICKMESSAGE, name.c_str(), kicker.c_str(), reason.c_str()); + PSendSysMessage(LANG_COMMAND_KICKMESSAGE,nameLink.c_str()); } } else { - PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER, name.c_str()); + PSendSysMessage(LANG_COMMAND_KICKNOTFOUNDPLAYER,nameLink.c_str()); return false; } } return true; } +//set temporary phase mask for player +bool ChatHandler::HandleModifyPhaseCommand(const char* args) +{ + if (!*args) + return false; + + uint32 phasemask = (uint32)atoi((char*)args); + + Unit *target = getSelectedUnit(); + if(!target) + target = m_session->GetPlayer(); + + // check online security + else if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + + target->SetPhaseMask(phasemask,true); + + return true; +} + //show info of player bool ChatHandler::HandlePInfoCommand(const char* args) { @@ -1783,12 +1783,8 @@ bool ChatHandler::HandlePInfoCommand(const char* args) if (px) { - name = px; - + name = extractPlayerNameFromLink(px); if(name.empty()) - return false; - - if(!normalizePlayerName(name)) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -1829,6 +1825,10 @@ bool ChatHandler::HandlePInfoCommand(const char* args) // get additional information from Player object if(target) { + // check online security + if (HasLowerSecurity(target, 0)) + return false; + targetGUID = target->GetGUID(); name = target->GetName(); // re-read for case getSelectedPlayer() target accId = target->GetSession()->GetAccountId(); @@ -1840,6 +1840,11 @@ bool ChatHandler::HandlePInfoCommand(const char* args) // get additional information from DB else { + // check offline security + if (HasLowerSecurity(NULL, targetGUID)) + return false; + + // 0 QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", GUID_LOPART(targetGUID)); if (!result) { @@ -1890,7 +1895,9 @@ bool ChatHandler::HandlePInfoCommand(const char* args) delete result; } - PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetTrinityString(LANG_OFFLINE)), name.c_str(), GUID_LOPART(targetGUID), username.c_str(), accId, security, last_ip.c_str(), last_login.c_str(), latency); + std::string nameLink = playerLink(name); + + PSendSysMessage(LANG_PINFO_ACCOUNT, (target?"":GetMangosString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(targetGUID), username.c_str(), accId, security, last_ip.c_str(), last_login.c_str(), latency); std::string timeStr = secsToTimeString(total_player_time,true,true); uint32 gold = money /GOLD; @@ -1940,6 +1947,191 @@ bool ChatHandler::HandlePInfoCommand(const char* args) return true; } +/*//show tickets +void ChatHandler::ShowTicket(uint64 guid, char const* text, char const* time) +{ + std::string name; + if(!objmgr.GetPlayerNameByGUID(guid,name)) + name = GetTrinityString(LANG_UNKNOWN); + + std::string nameLink = playerLink(name); + + PSendSysMessage(LANG_COMMAND_TICKETVIEW, nameLink.c_str(),time,text); +} + +//ticket commands +bool ChatHandler::HandleTicketCommand(const char* args) +{ + char* px = strtok((char*)args, " "); + + // ticket<end> + if (!px) + { + if(!m_session) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + size_t count = ticketmgr.GetTicketCount(); + + bool accept = m_session->GetPlayer()->isAcceptTickets(); + + PSendSysMessage(LANG_COMMAND_TICKETCOUNT, count, accept ? GetTrinityString(LANG_ON) : GetTrinityString(LANG_OFF)); + return true; + } + + // ticket on + if(strncmp(px,"on",3) == 0) + { + if(!m_session) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + m_session->GetPlayer()->SetAcceptTicket(true); + SendSysMessage(LANG_COMMAND_TICKETON); + return true; + } + + // ticket off + if(strncmp(px,"off",4) == 0) + { + if(!m_session) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + m_session->GetPlayer()->SetAcceptTicket(false); + SendSysMessage(LANG_COMMAND_TICKETOFF); + return true; + } + + // ticket #num + int num = atoi(px); + if(num > 0) + { + QueryResult *result = CharacterDatabase.PQuery("SELECT guid,ticket_text,ticket_lastchange FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_, num-1); + + if(!result) + { + PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num); + SetSentErrorMessage(true); + return false; + } + + Field* fields = result->Fetch(); + + uint32 guid = fields[0].GetUInt32(); + char const* text = fields[1].GetString(); + char const* time = fields[2].GetString(); + + ShowTicket(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),text,time); + delete result; + return true; + } + + std::string name = extractPlayerNameFromLink(px); + if(name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = objmgr.GetPlayerGUIDByName(name); + + if(!guid) + return false; + + // ticket $char_name + GMTicket* ticket = ticketmgr.GetGMTicket(GUID_LOPART(guid)); + if(!ticket) + return false; + + std::string time = TimeToTimestampStr(ticket->GetLastUpdate()); + + ShowTicket(guid, ticket->GetText(), time.c_str()); + + return true; +} + +//dell all tickets +bool ChatHandler::HandleDelTicketCommand(const char *args) +{ + char* px = strtok((char*)args, " "); + if (!px) + return false; + + // delticket all + if(strncmp(px,"all",4) == 0) + { + ticketmgr.DeleteAll(); + SendSysMessage(LANG_COMMAND_ALLTICKETDELETED); + return true; + } + + int num = (uint32)atoi(px); + + // delticket #num + if(num > 0) + { + QueryResult* result = CharacterDatabase.PQuery("SELECT guid FROM character_ticket ORDER BY ticket_id ASC "_OFFSET_,num-1); + if(!result) + { + PSendSysMessage(LANG_COMMAND_TICKENOTEXIST, num); + SetSentErrorMessage(true); + return false; + } + Field* fields = result->Fetch(); + uint32 guid = fields[0].GetUInt32(); + delete result; + + ticketmgr.Delete(guid); + + //notify player + if(Player* pl = objmgr.GetPlayer(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER))) + { + pl->GetSession()->SendGMTicketGetTicket(0x0A, 0); + PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL, GetNameLink(pl).c_str()); + } + else + PSendSysMessage(LANG_COMMAND_TICKETDEL); + + return true; + } + + std::string name = extractPlayerNameFromLink(px); + if(name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + uint64 guid = objmgr.GetPlayerGUIDByName(name); + + if(!guid) + return false; + + // delticket $char_name + ticketmgr.Delete(GUID_LOPART(guid)); + + // notify players about ticket deleting + if(Player* sender = objmgr.GetPlayer(guid)) + sender->GetSession()->SendGMTicketGetTicket(0x0A,0); + + std::string nameLink = playerLink(name); + + PSendSysMessage(LANG_COMMAND_TICKETPLAYERDEL,nameLink.c_str()); + return true; +}*/ + //set spawn dist of creature bool ChatHandler::HandleNpcSpawnDistCommand(const char* args) { @@ -2569,7 +2761,7 @@ bool ChatHandler::HandleWpModifyCommand(const char* args) wpCreature->AddObjectToRemoveList(); // re-create Creature* wpCreature2 = new Creature; - if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, VISUAL_WAYPOINT, 0)) + if (!wpCreature2->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), VISUAL_WAYPOINT, 0)) { PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, VISUAL_WAYPOINT); delete wpCreature2; @@ -2584,7 +2776,7 @@ bool ChatHandler::HandleWpModifyCommand(const char* args) return false; } - wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + wpCreature2->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); wpCreature2->LoadFromDB(wpCreature2->GetDBTableGUIDLow(), map); map->Add(wpCreature2); @@ -2618,7 +2810,6 @@ bool ChatHandler::HandleWpModifyCommand(const char* args) } PSendSysMessage(LANG_WAYPOINT_CHANGED_NO, show_str); - return true; } @@ -2800,7 +2991,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) float o = chr->GetOrientation(); Creature* wpCreature = new Creature; - if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0)) + if (!wpCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0)) { PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete wpCreature; @@ -2822,7 +3013,8 @@ bool ChatHandler::HandleWpShowCommand(const char* args) // set "wpguid" column to the visual waypoint WorldDatabase.PExecuteLog("UPDATE waypoint_data SET wpguid = '%u' WHERE id = '%u' and point = '%u'", wpCreature->GetGUIDLow(), pathid, point); - wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + wpCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); + // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells(); wpCreature->LoadFromDB(wpCreature->GetDBTableGUIDLow(),map); map->Add(wpCreature); @@ -2863,7 +3055,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) Map *map = chr->GetMap(); Creature* pCreature = new Creature; - if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, id, 0)) + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT),map, chr->GetPhaseMaskForSpawn(), id, 0)) { PSendSysMessage(LANG_WAYPOINT_VP_NOTCREATED, id); delete pCreature; @@ -2881,7 +3073,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) return false; } - pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map); map->Add(pCreature); @@ -2928,7 +3120,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) Map *map = chr->GetMap(); Creature* pCreature = new Creature; - if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, id, 0)) + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, chr->GetPhaseMaskForSpawn(), id, 0)) { PSendSysMessage(LANG_WAYPOINT_NOTCREATED, id); delete pCreature; @@ -2946,7 +3138,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) return false; } - pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + pCreature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), chr->GetPhaseMaskForSpawn()); pCreature->LoadFromDB(pCreature->GetDBTableGUIDLow(), map); map->Add(pCreature); @@ -3028,9 +3220,8 @@ bool ChatHandler::HandleRenameCommand(const char* args) if(px) { - oldname = px; - - if(!normalizePlayerName(oldname)) + oldname = extractPlayerNameFromLink(px); + if(oldname.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -3057,19 +3248,83 @@ bool ChatHandler::HandleRenameCommand(const char* args) if(target) { - PSendSysMessage(LANG_RENAME_PLAYER, target->GetName()); + // check online security + if (HasLowerSecurity(target, 0)) + return false; + + PSendSysMessage(LANG_RENAME_PLAYER, GetNameLink(target).c_str()); target->SetAtLoginFlag(AT_LOGIN_RENAME); CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", target->GetGUIDLow()); } else { - PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldname.c_str(), GUID_LOPART(targetGUID)); + // check offline security + if (HasLowerSecurity(NULL, targetGUID)) + return false; + + std::string oldNameLink = playerLink(oldname); + + PSendSysMessage(LANG_RENAME_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGUID)); CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '1' WHERE guid = '%u'", GUID_LOPART(targetGUID)); } return true; } +// customize characters +bool ChatHandler::HandleCustomizeCommand(const char* args) +{ + Player* target = NULL; + uint64 targetGUID = 0; + std::string oldname; + + char* px = strtok((char*)args, " "); + + if(px) + { + oldname = extractPlayerNameFromLink(px); + if(oldname.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + target = objmgr.GetPlayer(oldname.c_str()); + + if (!target) + targetGUID = objmgr.GetPlayerGUIDByName(oldname); + } + + if(!target && !targetGUID) + { + target = getSelectedPlayer(); + } + + if(!target && !targetGUID) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + if(target) + { + PSendSysMessage(LANG_CUSTOMIZE_PLAYER, GetNameLink(target).c_str()); + target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow()); + } + else + { + std::string oldNameLink = playerLink(oldname); + + PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldNameLink.c_str(), GUID_LOPART(targetGUID)); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", GUID_LOPART(targetGUID)); + } + + return true; +} + //spawn go bool ChatHandler::HandleGameObjectCommand(const char* args) { @@ -3108,7 +3363,7 @@ bool ChatHandler::HandleGameObjectCommand(const char* args) GameObject* pGameObj = new GameObject; uint32 db_lowGUID = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); - if(!pGameObj->Create(db_lowGUID, goI->id, map, x, y, z, o, 0, 0, rot2, rot3, 0, 1)) + if(!pGameObj->Create(db_lowGUID, goI->id, map, chr->GetPhaseMaskForSpawn(), x, y, z, o, 0, 0, rot2, rot3, 0, 1)) { delete pGameObj; return false; @@ -3122,7 +3377,7 @@ bool ChatHandler::HandleGameObjectCommand(const char* args) } // fill the gameobject data and save to the db - pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode())); + pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()),chr->GetPhaseMaskForSpawn()); // this will generate a new guid if the object is in an instance if(!pGameObj->LoadFromDB(db_lowGUID, map)) @@ -3178,6 +3433,10 @@ bool ChatHandler::HandleAddHonorCommand(const char* args) return false; } + // check online security + if (HasLowerSecurity(target, 0)) + return false; + uint32 amount = (uint32)atoi(args); target->RewardHonor(NULL, 1, amount); return true; @@ -3193,6 +3452,10 @@ bool ChatHandler::HandleHonorAddKillCommand(const char* /*args*/) return false; } + // check online security + if (target->GetTypeId() == TYPEID_PLAYER && HasLowerSecurity((Player*)target, 0)) + return false; + m_session->GetPlayer()->RewardHonor(target, 1); return true; } @@ -3207,6 +3470,10 @@ bool ChatHandler::HandleUpdateHonorFieldsCommand(const char* /*args*/) return false; } + // check online security + if (HasLowerSecurity(target, 0)) + return false; + target->UpdateHonorFields(); return true; } @@ -3423,9 +3690,8 @@ bool ChatHandler::HandleCombatStopCommand(const char* args) if(*args) { - std::string playername = args; - - if(!normalizePlayerName(playername)) + std::string playername = extractPlayerNameFromLink((char*)args); + if(playername.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -3449,6 +3715,10 @@ bool ChatHandler::HandleCombatStopCommand(const char* args) player = m_session->GetPlayer(); } + // check online security + if (HasLowerSecurity(player, 0)) + return false; + player->CombatStop(); player->getHostilRefManager().deleteReferences(); return true; @@ -3487,7 +3757,7 @@ bool ChatHandler::HandleLearnAllCraftsCommand(const char* /*args*/) if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) continue; - m_session->GetPlayer()->learnSpell(skillLine->spellId); + m_session->GetPlayer()->learnSpell(skillLine->spellId,false); } } } @@ -3560,7 +3830,7 @@ bool ChatHandler::HandleLearnAllRecipesCommand(const char* args) continue; if( !target->HasSpell(spellInfo->Id) ) - m_session->GetPlayer()->learnSpell(skillLine->spellId); + m_session->GetPlayer()->learnSpell(skillLine->spellId,false); } uint16 maxLevel = target->GetPureMaxSkillValue(skillInfo->id); @@ -3688,12 +3958,50 @@ bool ChatHandler::HandleRepairitemsCommand(const char* /*args*/) return false; } + // check online security + if (HasLowerSecurity(target, 0)) + return false; + // Repair items target->DurabilityRepairAll(false, 0, false); - PSendSysMessage(LANG_YOU_REPAIR_ITEMS, target->GetName()); + PSendSysMessage(LANG_YOU_REPAIR_ITEMS, GetNameLink(target).c_str()); if(needReportToTarget(target)) - ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetName()); + ChatHandler(target).PSendSysMessage(LANG_YOUR_ITEMS_REPAIRED, GetNameLink().c_str()); + return true; +} + +bool ChatHandler::HandleWaterwalkCommand(const char* args) +{ + if(!*args) + return false; + + Player *player = getSelectedPlayer(); + + if(!player) + { + PSendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; + } + + // check online security + if (HasLowerSecurity(player, 0)) + return false; + + if (strncmp(args, "on", 3) == 0) + player->SetMovement(MOVE_WATER_WALK); // ON + else if (strncmp(args, "off", 4) == 0) + player->SetMovement(MOVE_LAND_WALK); // OFF + else + { + SendSysMessage(LANG_USE_BOL); + return false; + } + + PSendSysMessage(LANG_YOU_SET_WATERWALK, args, GetNameLink(player).c_str()); + if(needReportToTarget(player)) + ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetNameLink().c_str()); return true; } @@ -3753,6 +4061,72 @@ bool ChatHandler::HandleNpcUnFollowCommand(const char* /*args*/) return true; } +bool ChatHandler::HandleNpcTameCommand(const char* /*args*/) +{ + Creature *creatureTarget = getSelectedCreature (); + if (!creatureTarget || creatureTarget->isPet ()) + { + PSendSysMessage (LANG_SELECT_CREATURE); + SetSentErrorMessage (true); + return false; + } + + Player *player = m_session->GetPlayer (); + + if(player->GetPetGUID ()) + { + SendSysMessage (LANG_YOU_ALREADY_HAVE_PET); + SetSentErrorMessage (true); + return false; + } + + CreatureInfo const* cInfo = creatureTarget->GetCreatureInfo(); + + if (!cInfo->isTameable ()) + { + PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); + SetSentErrorMessage (true); + return false; + } + + // Everything looks OK, create new pet + Pet* pet = player->CreateTamedPetFrom (creatureTarget); + if (!pet) + { + PSendSysMessage (LANG_CREATURE_NON_TAMEABLE,cInfo->Entry); + SetSentErrorMessage (true); + return false; + } + + // place pet before player + float x,y,z; + player->GetClosePoint (x,y,z,creatureTarget->GetObjectSize (),CONTACT_DISTANCE); + pet->Relocate (x,y,z,M_PI-player->GetOrientation ()); + + // set pet to defensive mode by default (some classes can't control controlled pets in fact). + pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE); + + // calculate proper level + uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->getLevel() - 5) : creatureTarget->getLevel(); + + // prepare visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); + + // add to world + pet->GetMap()->Add((Creature*)pet); + + // visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); + + // caster have pet now + player->SetPet(pet); + + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + player->PetSpellInitialize(); + + return true; +} + bool ChatHandler::HandleCreatePetCommand(const char* args) { Player *player = m_session->GetPlayer(); @@ -3912,7 +4286,7 @@ bool ChatHandler::HandlePetTpCommand(const char *args) uint32 tp = atol(args); - pet->SetTP(tp); + //pet->SetTP(tp); PSendSysMessage("Pet's tp changed to %u", tp); return true; @@ -4053,3 +4427,71 @@ bool ChatHandler::HandleNpcAddFormationCommand(const char* args) return true; } + +//change phasemask of creature or pet +bool ChatHandler::HandleNpcSetPhaseCommand(const char* args) +{ + if (!*args) + return false; + + uint32 phasemask = (uint32) atoi((char*)args); + if ( phasemask == 0 ) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + Creature* pCreature = getSelectedCreature(); + if(!pCreature) + { + SendSysMessage(LANG_SELECT_CREATURE); + SetSentErrorMessage(true); + return false; + } + + pCreature->SetPhaseMask(phasemask,true); + + if(!pCreature->isPet()) + pCreature->SaveToDB(); + + return true; +} + +//set pahsemask for selected object +bool ChatHandler::HandleGOPhaseCommand(const char* args) +{ + // number or [name] Shift-click form |color|Hgameobject:go_id|h[name]|h|r + char* cId = extractKeyFromLink((char*)args,"Hgameobject"); + if(!cId) + return false; + + uint32 lowguid = atoi(cId); + if(!lowguid) + return false; + + GameObject* obj = NULL; + // by DB guid + if (GameObjectData const* go_data = objmgr.GetGOData(lowguid)) + obj = GetObjectGlobalyWithGuidOrNearWithDbGuid(lowguid,go_data->id); + + if(!obj) + { + PSendSysMessage(LANG_COMMAND_OBJNOTFOUND, lowguid); + SetSentErrorMessage(true); + return false; + } + + char* phaseStr = strtok (NULL, " "); + uint32 phasemask = phaseStr? atoi(phaseStr) : 0; + if ( phasemask == 0 ) + { + SendSysMessage(LANG_BAD_VALUE); + SetSentErrorMessage(true); + return false; + } + + obj->SetPhaseMask(phasemask,true); + obj->SaveToDB(); + return true; +} diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index a36571d20a4..03979dc63e9 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -1,7 +1,7 @@ /* -* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * -* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -56,12 +56,12 @@ bool ChatHandler::HandleAHBotOptionsCommand(const char* args) { - uint32 ahMapID = 0; + AuctionLocation ahMapID = AUCTION_NEUTRAL; char * opt = strtok((char*)args, " "); char * ahMapIdStr = strtok(NULL, " "); if (ahMapIdStr) { - ahMapID = (uint32) strtoul(ahMapIdStr, NULL, 0); + ahMapID = (AuctionLocation) strtoul(ahMapIdStr, NULL, 0); } if (!opt) { @@ -427,17 +427,8 @@ bool ChatHandler::HandleAHBotOptionsCommand(const char* args) } //reload commands -bool ChatHandler::HandleReloadCommand(const char* arg) -{ - // this is error catcher for wrong table name in .reload commands - PSendSysMessage("Db table with name starting from '%s' not found and can't be reloaded.",arg); - SetSentErrorMessage(true); - return false; -} - bool ChatHandler::HandleReloadAllCommand(const char*) { - HandleReloadAreaTriggerTeleportCommand(""); HandleReloadSkillFishingBaseLevelCommand(""); HandleReloadAllAreaCommand(""); @@ -522,6 +513,7 @@ bool ChatHandler::HandleReloadAllSpellCommand(const char*) HandleReloadSpellElixirCommand("a"); HandleReloadSpellLearnSpellCommand("a"); HandleReloadSpellProcEventCommand("a"); + HandleReloadSpellBonusesCommand("a"); HandleReloadSpellScriptTargetCommand("a"); HandleReloadSpellTargetPositionCommand("a"); HandleReloadSpellThreatsCommand("a"); @@ -624,6 +616,11 @@ bool ChatHandler::HandleReloadQuestTemplateCommand(const char*) sLog.outString( "Re-Loading Quest Templates..." ); objmgr.LoadQuests(); SendGlobalGMSysMessage("DB table `quest_template` (quest definitions) reloaded."); + + /// dependent also from `gameobject` but this table not reloaded anyway + sLog.outString( "Re-Loading GameObjects for quests..." ); + objmgr.LoadGameObjectForQuests(); + SendGlobalGMSysMessage("Data GameObjects for quests reloaded."); return true; } @@ -672,6 +669,15 @@ bool ChatHandler::HandleReloadLootTemplatesItemCommand(const char*) return true; } +bool ChatHandler::HandleReloadLootTemplatesMillingCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`milling_loot_template`)" ); + LoadLootTemplates_Milling(); + LootTemplates_Milling.CheckLootRefs(); + SendGlobalSysMessage("DB table `milling_loot_template` reloaded."); + return true; +} + bool ChatHandler::HandleReloadLootTemplatesPickpocketingCommand(const char*) { sLog.outString( "Re-Loading Loot Tables... (`pickpocketing_loot_template`)" ); @@ -716,6 +722,15 @@ bool ChatHandler::HandleReloadLootTemplatesSkinningCommand(const char*) return true; } +bool ChatHandler::HandleReloadLootTemplatesSpellCommand(const char*) +{ + sLog.outString( "Re-Loading Loot Tables... (`spell_loot_template`)" ); + LoadLootTemplates_Spell(); + LootTemplates_Spell.CheckLootRefs(); + SendGlobalSysMessage("DB table `spell_loot_template` reloaded."); + return true; +} + bool ChatHandler::HandleReloadTrinityStringCommand(const char*) { sLog.outString( "Re-Loading trinity_string Table!" ); @@ -828,6 +843,14 @@ bool ChatHandler::HandleReloadSpellProcEventCommand(const char*) return true; } +bool ChatHandler::HandleReloadSpellBonusesCommand(const char*) +{ + sLog.outString( "Re-Loading Spell Bonus Data..." ); + spellmgr.LoadSpellBonusess(); + SendGlobalSysMessage("DB table `spell_bonus_data` (spell damage/healing coefficients) reloaded."); + return true; +} + bool ChatHandler::HandleReloadSpellScriptTargetCommand(const char*) { sLog.outString( "Re-Loading SpellsScriptTarget..." ); @@ -1213,19 +1236,10 @@ bool ChatHandler::HandleAccountSetPasswordCommand(const char* args) return false; } - uint32 targetSecurity = accmgr.GetSecurity(targetAccountId); - - /// m_session==NULL only for console - uint32 plSecurity = m_session ? m_session->GetSecurity() : SEC_CONSOLE; - /// can set password only for target with less security /// This is also reject self apply in fact - if (targetSecurity >= plSecurity) - { - SendSysMessage (LANG_YOURS_SECURITY_IS_LOW); - SetSentErrorMessage (true); + if(HasLowerSecurityAccount (NULL,targetAccountId,true)) return false; - } if (strcmp(szPassword1,szPassword2)) { @@ -1303,7 +1317,6 @@ bool ChatHandler::HandleSetSkillCommand(const char* args) char *max_p = strtok (NULL, " "); int32 skill = atoi(skill_p); - if (skill <= 0) { PSendSysMessage(LANG_INVALID_SKILL_ID, skill); @@ -1329,9 +1342,11 @@ bool ChatHandler::HandleSetSkillCommand(const char* args) return false; } + std::string tNameLink = GetNameLink(target); + if(!target->GetSkillValue(skill)) { - PSendSysMessage(LANG_SET_SKILL_ERROR, target->GetName(), skill, sl->name[0]); + PSendSysMessage(LANG_SET_SKILL_ERROR, tNameLink.c_str(), skill, sl->name[0]); SetSentErrorMessage(true); return false; } @@ -1342,7 +1357,7 @@ bool ChatHandler::HandleSetSkillCommand(const char* args) return false; target->SetSkill(skill, level, max); - PSendSysMessage(LANG_SET_SKILL, skill, sl->name[0], target->GetName(), level, max); + PSendSysMessage(LANG_SET_SKILL, skill, sl->name[0], tNameLink.c_str(), level, max); return true; } @@ -1353,27 +1368,12 @@ bool ChatHandler::HandleUnLearnCommand(const char* args) return false; // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r - uint32 min_id = extractSpellIdFromLink((char*)args); - if(!min_id) + uint32 spell_id = extractSpellIdFromLink((char*)args); + if(!spell_id) return false; - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r - char* tail = strtok(NULL,""); - - uint32 max_id = extractSpellIdFromLink(tail); - - if (!max_id) - { - // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r - max_id = min_id+1; - } - else - { - if (max_id < min_id) - std::swap(min_id,max_id); - - max_id=max_id+1; - } + char const* allStr = strtok(NULL," "); + bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false; Player* target = getSelectedPlayer(); if(!target) @@ -1383,13 +1383,13 @@ bool ChatHandler::HandleUnLearnCommand(const char* args) return false; } - for(uint32 spell=min_id;spell<max_id;spell++) - { - if (target->HasSpell(spell)) - target->removeSpell(spell); - else - SendSysMessage(LANG_FORGET_SPELL); - } + if(allRanks) + spell_id = spellmgr.GetFirstSpellInChain (spell_id); + + if (target->HasSpell(spell_id)) + target->removeSpell(spell_id,false,!allRanks); + else + SendSysMessage(LANG_FORGET_SPELL); return true; } @@ -1404,10 +1404,12 @@ bool ChatHandler::HandleCooldownCommand(const char* args) return false; } + std::string tNameLink = GetNameLink(target); + if (!*args) { target->RemoveAllSpellCooldown(); - PSendSysMessage(LANG_REMOVEALL_COOLDOWN, target->GetName()); + PSendSysMessage(LANG_REMOVEALL_COOLDOWN, tNameLink.c_str()); } else { @@ -1418,7 +1420,7 @@ bool ChatHandler::HandleCooldownCommand(const char* args) if(!sSpellStore.LookupEntry(spell_id)) { - PSendSysMessage(LANG_UNKNOWN_SPELL, target==m_session->GetPlayer() ? GetTrinityString(LANG_YOU) : target->GetName()); + PSendSysMessage(LANG_UNKNOWN_SPELL, target==m_session->GetPlayer() ? GetMangosString(LANG_YOU) : tNameLink.c_str()); SetSentErrorMessage(true); return false; } @@ -1428,8 +1430,8 @@ bool ChatHandler::HandleCooldownCommand(const char* args) data << uint64(target->GetGUID()); target->GetSession()->SendPacket(&data); target->RemoveSpellCooldown(spell_id); - PSendSysMessage(LANG_REMOVE_COOLDOWN, spell_id, target==m_session->GetPlayer() ? GetTrinityString(LANG_YOU) : target->GetName()); - } + PSendSysMessage(LANG_REMOVE_COOLDOWN, spell_id, target==m_session->GetPlayer() ? GetMangosString(LANG_YOU) : tNameLink.c_str()); + } return true; } @@ -2054,7 +2056,7 @@ bool ChatHandler::HandleLearnAllCommand(const char* /*args*/) continue; } - m_session->GetPlayer()->learnSpell(spell); + m_session->GetPlayer()->learnSpell(spell,false); } SendSysMessage(LANG_COMMAND_LEARN_MANY_SPELLS); @@ -2094,7 +2096,7 @@ bool ChatHandler::HandleLearnAllGMCommand(const char* /*args*/) continue; } - m_session->GetPlayer()->learnSpell(spell); + m_session->GetPlayer()->learnSpell(spell,false); } SendSysMessage(LANG_LEARNING_GM_SKILLS); @@ -2121,6 +2123,10 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/) if(!spellInfo) continue; + // skip server-side/triggered spells + if(spellInfo->spellLevel==0) + continue; + // skip wrong class/race skills if(!m_session->GetPlayer()->IsSpellFitByClassAndRace(spellInfo->Id)) continue; @@ -2129,8 +2135,6 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/) if( spellInfo->SpellFamilyName != family) continue; - //TODO: skip triggered spells - // skip spells with first rank learned as talent (and all talents then also) uint32 first_rank = spellmgr.GetFirstSpellInChain(spellInfo->Id); if(GetTalentSpellCost(first_rank) > 0 ) @@ -2140,27 +2144,13 @@ bool ChatHandler::HandleLearnAllMySpellsCommand(const char* /*args*/) if(!SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) continue; - m_session->GetPlayer()->learnSpell(i); + m_session->GetPlayer()->learnSpell(i,false); } SendSysMessage(LANG_COMMAND_LEARN_CLASS_SPELLS); return true; } -static void learnAllHighRanks(Player* player, uint32 spellid) -{ - SpellChainNode const* node; - do - { - node = spellmgr.GetSpellChainNode(spellid); - player->learnSpell(spellid); - if (!node) - break; - spellid=node->next; - } - while (node->next); -} - bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/) { Player* player = m_session->GetPlayer(); @@ -2198,11 +2188,8 @@ bool ChatHandler::HandleLearnAllMyTalentsCommand(const char* /*args*/) if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer(),false)) continue; - // learn highest rank of talent - player->learnSpell(spellid); - - // and learn all non-talent spell ranks (recursive by tree) - learnAllHighRanks(player,spellid); + // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree) + player->learnSpellHighRank(spellid); } SendSysMessage(LANG_COMMAND_LEARN_CLASS_TALENTS); @@ -2213,7 +2200,7 @@ bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/) { // skipping UNIVERSAL language (0) for(int i = 1; i < LANGUAGES_COUNT; ++i) - m_session->GetPlayer()->learnSpell(lang_description[i].spell_id); + m_session->GetPlayer()->learnSpell(lang_description[i].spell_id,false); SendSysMessage(LANG_COMMAND_LEARN_ALL_LANG); return true; @@ -2221,13 +2208,11 @@ bool ChatHandler::HandleLearnAllLangCommand(const char* /*args*/) bool ChatHandler::HandleLearnAllDefaultCommand(const char* args) { - char* pName = strtok((char*)args, ""); Player *player = NULL; - if (pName) + if (*args) { - std::string name = pName; - - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -2249,7 +2234,7 @@ bool ChatHandler::HandleLearnAllDefaultCommand(const char* args) player->learnDefaultSpells(); player->learnQuestRewardedSpells(); - PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST,player->GetName()); + PSendSysMessage(LANG_COMMAND_LEARN_ALL_DEFAULT_AND_QUEST,GetNameLink(player).c_str()); return true; } @@ -2269,25 +2254,31 @@ bool ChatHandler::HandleLearnCommand(const char* args) if(!spell || !sSpellStore.LookupEntry(spell)) return false; - if (targetPlayer->HasSpell(spell)) + char const* allStr = strtok(NULL," "); + bool allRanks = allStr ? (strncmp(allStr, "all", strlen(allStr)) == 0) : false; + + SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); + if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) { - if(targetPlayer == m_session->GetPlayer()) - SendSysMessage(LANG_YOU_KNOWN_SPELL); - else - PSendSysMessage(LANG_TARGET_KNOWN_SPELL,targetPlayer->GetName()); + PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); SetSentErrorMessage(true); return false; } - SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell); - if(!spellInfo || !SpellMgr::IsSpellValid(spellInfo,m_session->GetPlayer())) + if (!allRanks && targetPlayer->HasSpell(spell)) { - PSendSysMessage(LANG_COMMAND_SPELL_BROKEN,spell); + if(targetPlayer == m_session->GetPlayer()) + SendSysMessage(LANG_YOU_KNOWN_SPELL); + else + PSendSysMessage(LANG_TARGET_KNOWN_SPELL,GetNameLink(targetPlayer).c_str()); SetSentErrorMessage(true); return false; } - targetPlayer->learnSpell(spell); + if(allRanks) + targetPlayer->learnSpellHighRank(spell); + else + targetPlayer->learnSpell(spell,false); return true; } @@ -2357,7 +2348,7 @@ bool ChatHandler::HandleAddItemCommand(const char* args) if (count < 0) { plTarget->DestroyItemCount(itemId, -count, true, false); - PSendSysMessage(LANG_REMOVEITEM, itemId, -count, plTarget->GetName()); + PSendSysMessage(LANG_REMOVEITEM, itemId, -count, GetNameLink(plTarget).c_str()); return true; } @@ -3097,15 +3088,25 @@ bool ChatHandler::HandleLookupSkillCommand(const char* args) if(loc < MAX_LOCALE) { + char valStr[50] = ""; char const* knownStr = ""; if(target && target->HasSkill(id)) + { knownStr = GetTrinityString(LANG_KNOWN); + uint32 curValue = target->GetPureSkillValue(id); + uint32 maxValue = target->GetPureMaxSkillValue(id); + uint32 permValue = target->GetSkillPermBonusValue(id); + uint32 tempValue = target->GetSkillTempBonusValue(id); + + char const* valFormat = GetTrinityString(LANG_SKILL_VALUES); + snprintf(valStr,50,valFormat,curValue,maxValue,permValue,tempValue); + } // send skill in "id - [namedlink locale]" format if (m_session) - PSendSysMessage(LANG_SKILL_LIST_CHAT,id,id,name.c_str(),localeNames[loc],knownStr); + PSendSysMessage(LANG_SKILL_LIST_CHAT,id,id,name.c_str(),localeNames[loc],knownStr,valStr); else - PSendSysMessage(LANG_SKILL_LIST_CONSOLE,id,name.c_str(),localeNames[loc],knownStr); + PSendSysMessage(LANG_SKILL_LIST_CONSOLE,id,name.c_str(),localeNames[loc],knownStr,valStr); ++counter; } @@ -3172,7 +3173,7 @@ bool ChatHandler::HandleLookupSpellCommand(const char* args) bool talent = (talentCost > 0); bool passive = IsPassiveSpell(id); - bool active = target && (target->HasAura(id,0) || target->HasAura(id,1) || target->HasAura(id,2)); + bool active = target && target->HasAura(id); // unit32 used to prevent interpreting uint8 as char at output // find rank of learned spell for learning spell, or talent rank @@ -3519,11 +3520,11 @@ bool ChatHandler::HandleGuildInviteCommand(const char *args) if (!targetGuild) return false; - std::string plName = par1; - if (!normalizePlayerName (plName)) + std::string plName = extractPlayerNameFromLink(par1); + if(plName.empty()) { - SendSysMessage (LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage (true); + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); return false; } @@ -3531,7 +3532,7 @@ bool ChatHandler::HandleGuildInviteCommand(const char *args) if (Player* targetPlayer = ObjectAccessor::Instance ().FindPlayerByName (plName.c_str ())) plGuid = targetPlayer->GetGUID (); else - plGuid = objmgr.GetPlayerGUIDByName (plName.c_str ()); + plGuid = objmgr.GetPlayerGUIDByName (plName); if (!plGuid) false; @@ -3552,11 +3553,11 @@ bool ChatHandler::HandleGuildUninviteCommand(const char *args) if(!par1) return false; - std::string plName = par1; - if (!normalizePlayerName (plName)) + std::string plName = extractPlayerNameFromLink(par1); + if(plName.empty()) { - SendSysMessage (LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage (true); + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); return false; } @@ -3569,7 +3570,7 @@ bool ChatHandler::HandleGuildUninviteCommand(const char *args) } else { - plGuid = objmgr.GetPlayerGUIDByName (plName.c_str ()); + plGuid = objmgr.GetPlayerGUIDByName (plName); glId = Player::GetGuildIdFromDB (plGuid); } @@ -3594,14 +3595,16 @@ bool ChatHandler::HandleGuildRankCommand(const char *args) char* par2 = strtok (NULL, " "); if (!par1 || !par2) return false; - std::string plName = par1; - if (!normalizePlayerName (plName)) + + std::string plName = extractPlayerNameFromLink(par1); + if(plName.empty()) { - SendSysMessage (LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage (true); + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); return false; } + uint64 plGuid = 0; uint32 glId = 0; if (Player* targetPlayer = ObjectAccessor::Instance ().FindPlayerByName (plName.c_str ())) @@ -3611,7 +3614,7 @@ bool ChatHandler::HandleGuildRankCommand(const char *args) } else { - plGuid = objmgr.GetPlayerGUIDByName (plName.c_str ()); + plGuid = objmgr.GetPlayerGUIDByName (plName); glId = Player::GetGuildIdFromDB (plGuid); } @@ -3749,6 +3752,12 @@ bool ChatHandler::HandleDieCommand(const char* /*args*/) return false; } + if(target->GetTypeId()==TYPEID_PLAYER) + { + if(HasLowerSecurity((Player*)target,0,false)) + return false; + } + if( target->isAlive() ) { //m_session->GetPlayer()->DealDamage(target, target->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); @@ -3800,7 +3809,7 @@ bool ChatHandler::HandleDamageCommand(const char * args) SpellSchoolMask schoolmask = SpellSchoolMask(1 << school); if ( schoolmask & SPELL_SCHOOL_MASK_NORMAL ) - damage = m_session->GetPlayer()->CalcArmorReducedDamage(target, damage); + damage = m_session->GetPlayer()->CalcArmorReducedDamage(target, damage, NULL, BASE_ATTACK); char* spellStr = strtok((char*)NULL, " "); @@ -3850,7 +3859,7 @@ bool ChatHandler::HandleModifyArenaCommand(const char * args) target->ModifyArenaPoints(amount); - PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, target->GetName(), target->GetArenaPoints()); + PSendSysMessage(LANG_COMMAND_MODIFY_ARENA, GetNameLink(target).c_str(), target->GetArenaPoints()); return true; } @@ -3861,8 +3870,8 @@ bool ChatHandler::HandleReviveCommand(const char* args) if (*args) { - std::string name = args; - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -3889,10 +3898,6 @@ bool ChatHandler::HandleReviveCommand(const char* args) bool ChatHandler::HandleAuraCommand(const char* args) { - char* px = strtok((char*)args, " "); - if (!px) - return false; - Unit *target = getSelectedUnit(); if(!target) { @@ -3901,7 +3906,9 @@ bool ChatHandler::HandleAuraCommand(const char* args) return false; } - uint32 spellID = (uint32)atoi(px); + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellID = extractSpellIdFromLink((char*)args); + SpellEntry const *spellInfo = sSpellStore.LookupEntry( spellID ); if(spellInfo) { @@ -3925,10 +3932,6 @@ bool ChatHandler::HandleAuraCommand(const char* args) bool ChatHandler::HandleUnAuraCommand(const char* args) { - char* px = strtok((char*)args, " "); - if (!px) - return false; - Unit *target = getSelectedUnit(); if(!target) { @@ -3944,7 +3947,11 @@ bool ChatHandler::HandleUnAuraCommand(const char* args) return true; } - uint32 spellID = (uint32)atoi(px); + // number or [name] Shift-click form |color|Hspell:spell_id|h[name]|h|r or Htalent form + uint32 spellID = extractSpellIdFromLink((char*)args); + if(!spellID) + return false; + target->RemoveAurasDueToSpell(spellID); return true; @@ -4148,15 +4155,15 @@ bool ChatHandler::HandleExploreCheatCommand(const char* args) if (flag != 0) { - PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, chr->GetName()); + PSendSysMessage(LANG_YOU_SET_EXPLORE_ALL, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,GetName()); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_ALL,GetNameLink().c_str()); } else { - PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, chr->GetName()); + PSendSysMessage(LANG_YOU_SET_EXPLORE_NOTHING, GetNameLink(chr).c_str()); if (needReportToTarget(chr)) - ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,GetName()); + ChatHandler(chr).PSendSysMessage(LANG_YOURS_EXPLORE_SET_NOTHING,GetNameLink().c_str()); } for (uint8 i=0; i<128; i++) @@ -4193,36 +4200,6 @@ bool ChatHandler::HandleHoverCommand(const char* args) return true; } -bool ChatHandler::HandleWaterwalkCommand(const char* args) -{ - if(!args) - return false; - - Player *player = getSelectedPlayer(); - if(!player) - { - PSendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - - if (strncmp(args, "on", 3) == 0) - player->SetMovement(MOVE_WATER_WALK); // ON - else if (strncmp(args, "off", 4) == 0) - player->SetMovement(MOVE_LAND_WALK); // OFF - else - { - SendSysMessage(LANG_USE_BOL); - return false; - } - - PSendSysMessage(LANG_YOU_SET_WATERWALK, args, player->GetName()); - if(needReportToTarget(player)) - ChatHandler(player).PSendSysMessage(LANG_YOUR_WATERWALK_SET, args, GetName()); - return true; - -} - bool ChatHandler::HandleLevelUpCommand(const char* args) { char* px = strtok((char*)args, " "); @@ -4254,8 +4231,8 @@ bool ChatHandler::HandleLevelUpCommand(const char* args) if(pname) // player by name { - name = pname; - if(!normalizePlayerName(name)) + name = extractPlayerNameFromLink(pname); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -4285,7 +4262,7 @@ bool ChatHandler::HandleLevelUpCommand(const char* args) return false; } - name = chr->GetName(); + name = GetNameLink(chr); } assert(chr || chr_guid); @@ -4323,7 +4300,10 @@ bool ChatHandler::HandleLevelUpCommand(const char* args) } if(m_session->GetPlayer() != chr) // including chr==NULL - PSendSysMessage(LANG_YOU_CHANGE_LVL,name.c_str(),newlevel); + { + std::string nameLink = playerLink(name); + PSendSysMessage(LANG_YOU_CHANGE_LVL,nameLink.c_str(),newlevel); + } return true; } @@ -4332,8 +4312,6 @@ bool ChatHandler::HandleShowAreaCommand(const char* args) if (!*args) return false; - int area = atoi((char*)args); - Player *chr = getSelectedPlayer(); if (chr == NULL) { @@ -4342,10 +4320,11 @@ bool ChatHandler::HandleShowAreaCommand(const char* args) return false; } + int area = GetAreaFlagByAreaID(atoi((char*)args)); int offset = area / 32; uint32 val = (uint32)(1 << (area % 32)); - if(offset >= 128) + if(area<0 || offset >= 128) { SendSysMessage(LANG_BAD_VALUE); SetSentErrorMessage(true); @@ -4364,8 +4343,6 @@ bool ChatHandler::HandleHideAreaCommand(const char* args) if (!*args) return false; - int area = atoi((char*)args); - Player *chr = getSelectedPlayer(); if (chr == NULL) { @@ -4374,10 +4351,11 @@ bool ChatHandler::HandleHideAreaCommand(const char* args) return false; } + int area = GetAreaFlagByAreaID(atoi((char*)args)); int offset = area / 32; uint32 val = (uint32)(1 << (area % 32)); - if(offset >= 128) + if(area<0 || offset >= 128) { SendSysMessage(LANG_BAD_VALUE); SetSentErrorMessage(true); @@ -4723,11 +4701,28 @@ bool ChatHandler::HandleListAurasCommand (const char * /*args*/) for (Unit::AuraMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr) { bool talent = GetTalentSpellCost(itr->second->GetId()) > 0; - PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, itr->second->GetId(), itr->second->GetEffIndex(), - itr->second->GetModifier()->m_auraname, itr->second->GetAuraDuration(), itr->second->GetAuraMaxDuration(), - itr->second->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()], - (itr->second->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), - IS_PLAYER_GUID(itr->second->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(itr->second->GetCasterGUID())); + + char const* name = itr->second->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()]; + + if (m_session) + { + std::ostringstream ss_name; + ss_name << "|cffffffff|Hspell:" << itr->second->GetId() << "|h[" << name << "]|h|r"; + + PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, itr->second->GetId(), itr->second->GetEffIndex(), + itr->second->GetModifier()->m_auraname, itr->second->GetAuraDuration(), itr->second->GetAuraMaxDuration(), + ss_name.str().c_str(), + (itr->second->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID(itr->second->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(itr->second->GetCasterGUID())); + } + else + { + PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, itr->second->GetId(), itr->second->GetEffIndex(), + itr->second->GetModifier()->m_auraname, itr->second->GetAuraDuration(), itr->second->GetAuraMaxDuration(), + name, + (itr->second->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID(itr->second->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(itr->second->GetCasterGUID())); + } } for (int i = 0; i < TOTAL_AURAS; i++) { @@ -4737,11 +4732,65 @@ bool ChatHandler::HandleListAurasCommand (const char * /*args*/) for (Unit::AuraList::const_iterator itr = uAuraList.begin(); itr != uAuraList.end(); ++itr) { bool talent = GetTalentSpellCost((*itr)->GetId()) > 0; - PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), - (*itr)->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()],((*itr)->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), - IS_PLAYER_GUID((*itr)->GetCasterGUID()) ? "player" : "creature",GUID_LOPART((*itr)->GetCasterGUID())); + + char const* name = (*itr)->GetSpellProto()->SpellName[m_session->GetSessionDbcLocale()]; + + if (m_session) + { + std::ostringstream ss_name; + ss_name << "|cffffffff|Hspell:" << (*itr)->GetId() << "|h[" << name << "]|h|r"; + + PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), + ss_name.str().c_str(),((*itr)->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID((*itr)->GetCasterGUID()) ? "player" : "creature",GUID_LOPART((*itr)->GetCasterGUID())); + } + else + { + PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(), + name,((*itr)->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""), + IS_PLAYER_GUID((*itr)->GetCasterGUID()) ? "player" : "creature",GUID_LOPART((*itr)->GetCasterGUID())); + } + } + } + return true; +} + +bool ChatHandler::HandleResetAchievementsCommand (const char * args) +{ + char* pName = strtok((char*)args, ""); + Player *player = NULL; + uint64 guid = 0; + if (pName) + { + std::string name = extractPlayerNameFromLink(pName); + if(name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; } + + guid = objmgr.GetPlayerGUIDByName(name); + player = objmgr.GetPlayer(guid); } + else + { + player = getSelectedPlayer(); + if(player) + guid = player->GetGUID(); + } + + if(!player && !guid) + { + SendSysMessage(LANG_NO_CHAR_SELECTED); + return true; + } + + if(player) + player->GetAchievementMgr().Reset(); + else if(guid) + AchievementMgr::DeleteFromDB(GUID_LOPART(guid)); + return true; } @@ -4751,15 +4800,15 @@ bool ChatHandler::HandleResetHonorCommand (const char * args) Player *player = NULL; if (pName) { - std::string name = pName; - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink(pName); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); return false; } - uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str()); + uint64 guid = objmgr.GetPlayerGUIDByName(name); player = objmgr.GetPlayer(guid); } else @@ -4794,19 +4843,6 @@ static bool HandleResetStatsOrLevelHelper(Player* player) uint8 powertype = cEntry->powerType; - uint32 unitfield; - if(powertype == POWER_RAGE) - unitfield = 0x1100EE00; - else if(powertype == POWER_ENERGY) - unitfield = 0x00000000; - else if(powertype == POWER_MANA) - unitfield = 0x0000EE00; - else - { - sLog.outError("Invalid default powertype %u for player (class %u)",powertype,player->getClass()); - return false; - } - // reset m_form if no aura if(!player->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT)) player->m_form = FORM_NONE; @@ -4836,9 +4872,7 @@ static bool HandleResetStatsOrLevelHelper(Player* player) } } - // set UNIT_FIELD_BYTES_1 to init state but preserve m_form value - player->SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield); - player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_UNK5 ); + player->SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP ); player->SetByteValue(UNIT_FIELD_BYTES_2, 3, player->m_form); player->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); @@ -4856,15 +4890,15 @@ bool ChatHandler::HandleResetLevelCommand(const char * args) Player *player = NULL; if (pName) { - std::string name = pName; - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink(pName); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); return false; } - uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str()); + uint64 guid = objmgr.GetPlayerGUIDByName(name); player = objmgr.GetPlayer(guid); } else @@ -4880,17 +4914,26 @@ bool ChatHandler::HandleResetLevelCommand(const char * args) if(!HandleResetStatsOrLevelHelper(player)) return false; - player->SetLevel(1); + // set starting level + uint32 start_level = player->getClass() != CLASS_DEATH_KNIGHT + ? sWorld.getConfig(CONFIG_START_PLAYER_LEVEL) + : sWorld.getConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); + + player->SetLevel(start_level); + player->InitRunes(); player->InitStatsForLevel(true); player->InitTaxiNodesForLevel(); + player->InitGlyphsForLevel(); player->InitTalentForLevel(); player->SetUInt32Value(PLAYER_XP,0); // reset level to summoned pet Pet* pet = player->GetPet(); if(pet && pet->getPetType()==SUMMON_PET) + { pet->InitStatsForLevel(1); - + pet->InitTalentForLevel(); + } return true; } @@ -4900,15 +4943,15 @@ bool ChatHandler::HandleResetStatsCommand(const char * args) Player *player = NULL; if (pName) { - std::string name = pName; - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink(pName); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); return false; } - uint64 guid = objmgr.GetPlayerGUIDByName(name.c_str()); + uint64 guid = objmgr.GetPlayerGUIDByName(name); player = objmgr.GetPlayer(guid); } else @@ -4924,8 +4967,10 @@ bool ChatHandler::HandleResetStatsCommand(const char * args) if(!HandleResetStatsOrLevelHelper(player)) return false; + player->InitRunes(); player->InitStatsForLevel(true); player->InitTaxiNodesForLevel(); + player->InitGlyphsForLevel(); player->InitTalentForLevel(); return true; @@ -4938,9 +4983,8 @@ bool ChatHandler::HandleResetSpellsCommand(const char * args) uint64 playerGUID = 0; if (pName) { - std::string name = pName; - - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink(pName); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -4949,7 +4993,7 @@ bool ChatHandler::HandleResetSpellsCommand(const char * args) player = objmgr.GetPlayer(name.c_str()); if(!player) - playerGUID = objmgr.GetPlayerGUIDByName(name.c_str()); + playerGUID = objmgr.GetPlayerGUIDByName(name); } else player = getSelectedPlayer(); @@ -4966,9 +5010,8 @@ bool ChatHandler::HandleResetSpellsCommand(const char * args) player->resetSpells(); ChatHandler(player).SendSysMessage(LANG_RESET_SPELLS); - if(m_session->GetPlayer()!=player) - PSendSysMessage(LANG_RESET_SPELLS_ONLINE,player->GetName()); + PSendSysMessage(LANG_RESET_SPELLS_ONLINE,GetNameLink(player).c_str()); } else { @@ -4986,8 +5029,8 @@ bool ChatHandler::HandleResetTalentsCommand(const char * args) uint64 playerGUID = 0; if (pName) { - std::string name = pName; - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink(pName); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -4996,34 +5039,47 @@ bool ChatHandler::HandleResetTalentsCommand(const char * args) player = objmgr.GetPlayer(name.c_str()); if(!player) - playerGUID = objmgr.GetPlayerGUIDByName(name.c_str()); + playerGUID = objmgr.GetPlayerGUIDByName(name); } else player = getSelectedPlayer(); - if(!player && !playerGUID) - { - SendSysMessage(LANG_NO_CHAR_SELECTED); - SetSentErrorMessage(true); - return false; - } - if(player) { player->resetTalents(true); ChatHandler(player).SendSysMessage(LANG_RESET_TALENTS); - if(m_session->GetPlayer()!=player) - PSendSysMessage(LANG_RESET_TALENTS_ONLINE,player->GetName()); + PSendSysMessage(LANG_RESET_TALENTS_ONLINE,GetNameLink(player).c_str()); + + return true; } - else + else if (playerGUID) { CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE guid = '%u'",uint32(AT_LOGIN_RESET_TALENTS), GUID_LOPART(playerGUID) ); - PSendSysMessage(LANG_RESET_TALENTS_OFFLINE,pName); + std::string nameLink = playerLink(pName); + PSendSysMessage(LANG_RESET_TALENTS_OFFLINE,nameLink.c_str()); + return true; + } + // Try reset talenents as Hunter Pet + Creature* creature = getSelectedCreature(); + if (creature && creature->isPet() && ((Pet *)creature)->getPetType() == HUNTER_PET) + { + ((Pet *)creature)->resetTalents(true); + Unit *owner = creature->GetOwner(); + if (owner && owner->GetTypeId() == TYPEID_PLAYER) + { + player = (Player *)owner; + ChatHandler(player).SendSysMessage(LANG_RESET_TALENTS); + if(m_session->GetPlayer()!=player) + PSendSysMessage(LANG_RESET_TALENTS_ONLINE,GetNameLink(player).c_str()); + } + return true; } - return true; + SendSysMessage(LANG_NO_CHAR_SELECTED); + SetSentErrorMessage(true); + return false; } bool ChatHandler::HandleResetAllCommand(const char * args) @@ -5580,12 +5636,8 @@ bool ChatHandler::HandleBanInfoCharacterCommand(const char* args) if(!args) return false; - char* cname = strtok ((char*)args, ""); - if(!cname) - return false; - - std::string name = cname; - if(!normalizePlayerName(name)) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) { SendSysMessage(LANG_PLAYER_NOT_FOUND); SetSentErrorMessage(true); @@ -5897,8 +5949,8 @@ bool ChatHandler::HandleRespawnCommand(const char* /*args*/) cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - Trinity::RespawnDo u_do; - Trinity::WorldObjectWorker<Trinity::RespawnDo> worker(u_do); + MaNGOS::RespawnDo u_do; + MaNGOS::WorldObjectWorker<MaNGOS::RespawnDo> worker(pl,u_do); TypeContainerVisitor<Trinity::WorldObjectWorker<Trinity::RespawnDo>, GridTypeMapContainer > obj_worker(worker); CellLock<GridReadGuard> cell_lock(cell, p); @@ -5912,9 +5964,9 @@ bool ChatHandler::HandleFlyModeCommand(const char* args) if(!args) return false; - Unit *unit = getSelectedUnit(); - if (!unit || (unit->GetTypeId() != TYPEID_PLAYER)) - unit = m_session->GetPlayer(); + Player *target = getSelectedPlayer(); + if (!target) + target = m_session->GetPlayer(); WorldPacket data(12); if (strncmp(args, "on", 3) == 0) @@ -5926,10 +5978,10 @@ bool ChatHandler::HandleFlyModeCommand(const char* args) SendSysMessage(LANG_USE_BOL); return false; } - data.append(unit->GetPackGUID()); + data.append(target->GetPackGUID()); data << uint32(0); // unknown - unit->SendMessageToSet(&data, true); - PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, unit->GetName(), args); + target->SendMessageToSet(&data, true); + PSendSysMessage(LANG_COMMAND_FLYMODE_STATUS, GetNameLink(target).c_str(), args); return true; } @@ -6085,12 +6137,11 @@ bool ChatHandler::HandleWritePDumpCommand(const char *args) guid = atoi(p2); else { - std::string name = p2; - - if (!normalizePlayerName (name)) + std::string name = extractPlayerNameFromLink(p2); + if(name.empty()) { - SendSysMessage (LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage (true); + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); return false; } @@ -6682,8 +6733,15 @@ bool ChatHandler::HandleAccountSetAddonCommand(const char* args) SetSentErrorMessage(true); return false; } + } + // Let set addon state only for lesser (strong) security level + // or to self account + if (m_session && m_session->GetAccountId () != account_id && + HasLowerSecurityAccount (NULL,account_id,true)) + return false; + int lev=atoi(szExp); //get int anyway (0 if error) if(lev < 0) return false; @@ -6702,9 +6760,13 @@ bool ChatHandler::HandleSendItemsCommand(const char* args) // format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] - char* pName = strtok((char*)args, " "); - if(!pName) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); return false; + } char* tail1 = strtok(NULL, ""); if(!tail1) @@ -6742,8 +6804,7 @@ bool ChatHandler::HandleSendItemsCommand(const char* args) if (!msgText) return false; - // pName, msgSubject, msgText isn't NUL after prev. check - std::string name = pName; + // msgSubject, msgText isn't NUL after prev. check std::string subject = msgSubject; std::string text = msgText; @@ -6778,17 +6839,17 @@ bool ChatHandler::HandleSendItemsCommand(const char* args) } uint32 item_count = itemCountStr ? atoi(itemCountStr) : 1; - if(item_count < 1 || item_proto->MaxCount && item_count > item_proto->MaxCount) + if(item_count < 1 || item_proto->MaxCount > 0 && item_count > uint32(item_proto->MaxCount)) { PSendSysMessage(LANG_COMMAND_INVALID_ITEM_COUNT, item_count,item_id); SetSentErrorMessage(true); return false; } - while(item_count > item_proto->Stackable) + while(item_count > item_proto->GetMaxStackSize()) { - items.push_back(ItemPair(item_id,item_proto->Stackable)); - item_count -= item_proto->Stackable; + items.push_back(ItemPair(item_id,item_proto->GetMaxStackSize())); + item_count -= item_proto->GetMaxStackSize(); } items.push_back(ItemPair(item_id,item_count)); @@ -6801,13 +6862,6 @@ bool ChatHandler::HandleSendItemsCommand(const char* args) } } - if(!normalizePlayerName(name)) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - uint64 receiver_guid = objmgr.GetPlayerGUIDByName(name); if(!receiver_guid) { @@ -6839,7 +6893,8 @@ bool ChatHandler::HandleSendItemsCommand(const char* args) WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, &mi, 0, 0, MAIL_CHECK_MASK_NONE); - PSendSysMessage(LANG_MAIL_SENT, name.c_str()); + std::string nameLink = playerLink(name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); return true; } @@ -6851,9 +6906,13 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args) /// format: name "subject text" "mail text" money - char* pName = strtok((char*)args, " "); - if (!pName) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); return false; + } char* tail1 = strtok(NULL, ""); if (!tail1) @@ -6896,18 +6955,10 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args) if (money <= 0) return false; - // pName, msgSubject, msgText isn't NUL after prev. check - std::string name = pName; + // msgSubject, msgText isn't NUL after prev. check std::string subject = msgSubject; std::string text = msgText; - if (!normalizePlayerName(name)) - { - SendSysMessage(LANG_PLAYER_NOT_FOUND); - SetSentErrorMessage(true); - return false; - } - uint64 receiver_guid = objmgr.GetPlayerGUIDByName(name); if (!receiver_guid) { @@ -6929,7 +6980,8 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args) WorldSession::SendMailTo(receiver,messagetype, stationery, sender_guidlo, GUID_LOPART(receiver_guid), subject, itemTextId, NULL, money, 0, MAIL_CHECK_MASK_NONE); - PSendSysMessage(LANG_MAIL_SENT, name.c_str()); + std::string nameLink = playerLink(name); + PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); return true; } @@ -6937,15 +6989,16 @@ bool ChatHandler::HandleSendMoneyCommand(const char* args) bool ChatHandler::HandleSendMessageCommand(const char* args) { ///- Get the command line arguments - char* name_str = strtok((char*)args, " "); - char* msg_str = strtok(NULL, ""); - - if(!name_str || !msg_str) + std::string name = extractPlayerNameFromLink((char*)args); + if(name.empty()) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); return false; + } - std::string name = name_str; - - if(!normalizePlayerName(name)) + char* msg_str = strtok(NULL, ""); + if(!msg_str) return false; ///- Find the player and check that he is not logging out. @@ -6970,7 +7023,8 @@ bool ChatHandler::HandleSendMessageCommand(const char* args) rPlayer->GetSession()->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); //Confirmation message - PSendSysMessage(LANG_SENDMESSAGE,name.c_str(),msg_str); + std::string nameLink = playerLink(name); + PSendSysMessage(LANG_SENDMESSAGE,nameLink.c_str(),msg_str); return true; } @@ -6994,30 +7048,27 @@ bool ChatHandler::HandleModifyGenderCommand(const char *args) return false; } + PlayerInfo const* info = objmgr.GetPlayerInfo(player->getRace(), player->getClass()); + if(!info) + return false; + char const* gender_str = (char*)args; int gender_len = strlen(gender_str); - uint32 displayId = player->GetNativeDisplayId(); - char const* gender_full = NULL; - uint32 new_displayId = displayId; Gender gender; - if(!strncmp(gender_str,"male",gender_len)) // MALE + if(!strncmp(gender_str, "male", gender_len)) // MALE { if(player->getGender() == GENDER_MALE) return true; - gender_full = "male"; - new_displayId = player->getRace() == RACE_BLOODELF ? displayId+1 : displayId-1; gender = GENDER_MALE; } - else if (!strncmp(gender_str,"female",gender_len)) // FEMALE + else if (!strncmp(gender_str, "female", gender_len)) // FEMALE { if(player->getGender() == GENDER_FEMALE) return true; - gender_full = "female"; - new_displayId = player->getRace() == RACE_BLOODELF ? displayId-1 : displayId+1; gender = GENDER_FEMALE; } else @@ -7029,14 +7080,19 @@ bool ChatHandler::HandleModifyGenderCommand(const char *args) // Set gender player->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender); + player->SetByteValue(PLAYER_BYTES_3, 0, gender); // Change display ID - player->SetDisplayId(new_displayId); - player->SetNativeDisplayId(new_displayId); + player->SetDisplayId(gender ? info->displayId_f : info->displayId_m); + player->SetNativeDisplayId(gender ? info->displayId_f : info->displayId_m); + + char const* gender_full = gender ? "female" : "male"; + + PSendSysMessage(LANG_YOU_CHANGE_GENDER, GetNameLink(player).c_str(), gender_full); - PSendSysMessage(LANG_YOU_CHANGE_GENDER, player->GetName(),gender_full); if (needReportToTarget(player)) - ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full,GetName()); + ChatHandler(player).PSendSysMessage(LANG_YOUR_GENDER_CHANGED, gender_full, GetNameLink().c_str()); + return true; } diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp index a4a8a7a1f01..438b3922cb6 100644 --- a/src/game/LootHandler.cpp +++ b/src/game/LootHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -154,6 +154,7 @@ void WorldSession::HandleAutostoreLootItemOpcode( WorldPacket & recv_data ) --loot->unlootedCount; player->SendNewItem(newitem, uint32(item->count), false, false, true); + player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count); } else player->SendEquipError( msg, NULL, NULL ); @@ -326,7 +327,7 @@ void WorldSession::DoLootRelease( uint64 lguid ) int32 ReqValue = 175; LockEntry const *lockInfo = sLockStore.LookupEntry(go->GetGOInfo()->chest.lockId); if(lockInfo) - ReqValue = lockInfo->requiredminingskill; + ReqValue = lockInfo->Skill[0]; float skill = float(player->GetSkillValue(SKILL_MINING))/(ReqValue+25); double chance = pow(0.8*chance_rate,4*(1/double(max_amount))*double(uses)); if(roll_chance_f(100*chance+skill)) @@ -383,14 +384,22 @@ void WorldSession::DoLootRelease( uint64 lguid ) Item *pItem = player->GetItemByGuid(lguid ); if(!pItem) return; - if( (pItem->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP) && - pItem->GetProto()->Class == ITEM_CLASS_TRADE_GOODS && - pItem->GetCount() >= 5) + + ItemPrototype const* proto = pItem->GetProto(); + + // destroy only 5 items from stack in case prospecting and milling + if( (proto->BagFamily & (BAG_FAMILY_MASK_MINING_SUPP|BAG_FAMILY_MASK_HERBS)) && + proto->Class == ITEM_CLASS_TRADE_GOODS) { pItem->m_lootGenerated = false; pItem->loot.clear(); - uint32 count = 5; + uint32 count = pItem->GetCount(); + + // >=5 checked in spell code, but will work for cheating cases also with removing from another stacks. + if(count > 5) + count = 5; + player->DestroyItemCount(pItem, count, true); } else @@ -495,6 +504,7 @@ void WorldSession::HandleLootMasterGiveOpcode( WorldPacket & recv_data ) // not move item from loot to target inventory Item * newitem = target->StoreNewItem( dest, item.itemid, true, item.randomPropertyId ); target->SendNewItem(newitem, uint32(item.count), false, false, true ); + target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count); // mark as looted item.count=0; diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index 9271c14ed13..af310b452fe 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ #include "World.h" #include "Util.h" #include "SharedDefines.h" +#include "SpellMgr.h" static Rates const qualityToRate[MAX_ITEM_QUALITY] = { RATE_DROP_ITEM_POOR, // ITEM_QUALITY_POOR @@ -36,16 +37,18 @@ static Rates const qualityToRate[MAX_ITEM_QUALITY] = { RATE_DROP_ITEM_ARTIFACT, // ITEM_QUALITY_ARTIFACT }; -LootStore LootTemplates_Creature( "creature_loot_template", "creature entry"); -LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenchant id"); -LootStore LootTemplates_Fishing( "fishing_loot_template", "area id"); -LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry"); -LootStore LootTemplates_Item( "item_loot_template", "item entry"); -LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid"); -LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry"); -LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id"); -LootStore LootTemplates_Reference( "reference_loot_template", "reference id"); -LootStore LootTemplates_Skinning( "skinning_loot_template", "creature skinning id"); +LootStore LootTemplates_Creature( "creature_loot_template", "creature entry", true); +LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenchant id", true); +LootStore LootTemplates_Fishing( "fishing_loot_template", "area id", true); +LootStore LootTemplates_Gameobject( "gameobject_loot_template", "gameobject entry", true); +LootStore LootTemplates_Item( "item_loot_template", "item entry", true); +LootStore LootTemplates_Milling( "milling_loot_template", "item entry (herb)", true); +LootStore LootTemplates_Pickpocketing("pickpocketing_loot_template","creature pickpocket lootid", true); +LootStore LootTemplates_Prospecting( "prospecting_loot_template", "item entry (ore)", true); +LootStore LootTemplates_QuestMail( "quest_mail_loot_template", "quest id (with mail template)",false); +LootStore LootTemplates_Reference( "reference_loot_template", "reference id", false); +LootStore LootTemplates_Skinning( "skinning_loot_template", "creature skinning id", true); +LootStore LootTemplates_Spell( "spell_loot_template", "spell id (explicitly discovering ability)",false); class LootTemplate::LootGroup // A set of loot definitions for items (refs are not allowed) @@ -55,7 +58,7 @@ class LootTemplate::LootGroup // A set of loot def bool HasQuestDrop() const; // True if group includes at least 1 quest drop entry bool HasQuestDropForPlayer(Player const * player) const; // The same for active quests of the player - void Process(Loot& loot) const; // Rolls an item from the group (if any) and adds the item to the loot + void Process(Loot& loot, bool rate) const; // Rolls an item from the group (if any) and adds the item to the loot float RawTotalChance() const; // Overall chance for the group (without equal chanced items) float TotalChance() const; // Overall chance for the group @@ -66,7 +69,7 @@ class LootTemplate::LootGroup // A set of loot def LootStoreItemList ExplicitlyChanced; // Entries with chances defined in DB LootStoreItemList EqualChanced; // Zero chances - every entry takes the same chance - LootStoreItem const * Roll() const; // Rolls an item from the group, returns NULL if all miss their chances + LootStoreItem const * Roll(bool rate) const; // Rolls an item from the group, returns NULL if all miss their chances }; //Remove all data and free all memory @@ -230,17 +233,17 @@ void LootStore::ReportNotExistedId(uint32 id) const // Checks if the entry (quest, non-quest, reference) takes it's chance (at loot generation) // RATE_DROP_ITEMS is no longer used for all types of entries -bool LootStoreItem::Roll() const +bool LootStoreItem::Roll(bool rate) const { if(chance>=100.f) return true; if(mincountOrRef < 0) // reference case - return roll_chance_f(chance*sWorld.getRate(RATE_DROP_ITEM_REFERENCED)); + return roll_chance_f(chance* (rate ? sWorld.getRate(RATE_DROP_ITEM_REFERENCED) : 1.0f)); ItemPrototype const *pProto = objmgr.GetItemPrototype(itemid); - float qualityModifier = pProto ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; + float qualityModifier = pProto && rate ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; return roll_chance_f(chance*qualityModifier); } @@ -366,8 +369,12 @@ void Loot::AddItem(LootStoreItem const & item) } // Calls processor of corresponding LootTemplate (which handles everything including references) -void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner) +void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner, bool personal) { + // Must be provided + if(!loot_owner) + return; + LootTemplate const* tab = store.GetLootFor(loot_id); if (!tab) @@ -379,37 +386,36 @@ void Loot::FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner) items.reserve(MAX_NR_LOOT_ITEMS); quest_items.reserve(MAX_NR_QUEST_ITEMS); - tab->Process(*this, store); // Processing is done there, callback via Loot::AddItem() + tab->Process(*this, store,store.IsRatesAllowed ()); // Processing is done there, callback via Loot::AddItem() - // Setting access rights fow group-looting case - if(!loot_owner) - return; + // Setting access rights for group loot case Group * pGroup=loot_owner->GetGroup(); - if(!pGroup) - return; - for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + if(!personal && pGroup) { - //fill the quest item map for every player in the recipient's group - Player* pl = itr->getSource(); - if(!pl) - continue; - uint32 plguid = pl->GetGUIDLow(); - QuestItemMap::iterator qmapitr = PlayerQuestItems.find(plguid); - if (qmapitr == PlayerQuestItems.end()) - { - FillQuestLoot(pl); - } - qmapitr = PlayerFFAItems.find(plguid); - if (qmapitr == PlayerFFAItems.end()) - { - FillFFALoot(pl); - } - qmapitr = PlayerNonQuestNonFFAConditionalItems.find(plguid); - if (qmapitr == PlayerNonQuestNonFFAConditionalItems.end()) - { - FillNonQuestNonFFAConditionalLoot(pl); - } + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + if(Player* pl = itr->getSource()) + FillNotNormalLootFor(pl); } + // ... for personal loot + else + FillNotNormalLootFor(loot_owner); +} + +void Loot::FillNotNormalLootFor(Player* pl) +{ + uint32 plguid = pl->GetGUIDLow(); + + QuestItemMap::iterator qmapitr = PlayerQuestItems.find(plguid); + if (qmapitr == PlayerQuestItems.end()) + FillQuestLoot(pl); + + qmapitr = PlayerFFAItems.find(plguid); + if (qmapitr == PlayerFFAItems.end()) + FillFFALoot(pl); + + qmapitr = PlayerNonQuestNonFFAConditionalItems.find(plguid); + if (qmapitr == PlayerNonQuestNonFFAConditionalItems.end()) + FillNonQuestNonFFAConditionalLoot(pl); } QuestItemList* Loot::FillFFALoot(Player* player) @@ -640,6 +646,12 @@ LootItem* Loot::LootItemInSlot(uint32 lootSlot, Player* player, QuestItem **qite return item; } +uint32 Loot::GetMaxSlotInLootFor(Player* player) const +{ + QuestItemMap::const_iterator itr = PlayerQuestItems.find(player->GetGUIDLow()); + return items.size() + (itr != PlayerQuestItems.end() ? itr->second->size() : 0); +} + ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li) { b << uint32(li.itemid); @@ -653,12 +665,19 @@ ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li) ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) { + if (lv.permission == NONE_PERMISSION) + { + b << uint32(0); //gold + b << uint8(0); // item count + return b; // nothing output more + } + Loot &l = lv.loot; uint8 itemsShown = 0; //gold - b << uint32(lv.permission!=NONE_PERMISSION ? l.gold : 0); + b << uint32(l.gold); size_t count_pos = b.wpos(); // pos of item count byte b << uint8(0); // item count placeholder @@ -697,19 +716,21 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) } break; } - case NONE_PERMISSION: default: return b; // nothing output more } - if (lv.qlist) + QuestItemMap const& lootPlayerQuestItems = l.GetPlayerQuestItems(); + QuestItemMap::const_iterator q_itr = lootPlayerQuestItems.find(lv.viewer->GetGUIDLow()); + if (q_itr != lootPlayerQuestItems.end()) { - for (QuestItemList::iterator qi = lv.qlist->begin() ; qi != lv.qlist->end(); ++qi) + QuestItemList *q_list = q_itr->second; + for (QuestItemList::iterator qi = q_list->begin() ; qi != q_list->end(); ++qi) { LootItem &item = l.quest_items[qi->index]; if (!qi->is_looted && !item.is_looted) { - b << uint8(l.items.size() + (qi - lv.qlist->begin())); + b << uint8(l.items.size() + (qi - q_list->begin())); b << item; b << uint8(0); // allow loot ++itemsShown; @@ -717,9 +738,12 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) } } - if (lv.ffalist) + QuestItemMap const& lootPlayerFFAItems = l.GetPlayerFFAItems(); + QuestItemMap::const_iterator ffa_itr = lootPlayerFFAItems.find(lv.viewer->GetGUIDLow()); + if (ffa_itr != lootPlayerFFAItems.end()) { - for (QuestItemList::iterator fi = lv.ffalist->begin() ; fi != lv.ffalist->end(); ++fi) + QuestItemList *ffa_list = ffa_itr->second; + for (QuestItemList::iterator fi = ffa_list->begin() ; fi != ffa_list->end(); ++fi) { LootItem &item = l.items[fi->index]; if (!fi->is_looted && !item.is_looted) @@ -731,9 +755,12 @@ ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv) } } - if (lv.conditionallist) + QuestItemMap const& lootPlayerNonQuestNonFFAConditionalItems = l.GetPlayerNonQuestNonFFAConditionalItems(); + QuestItemMap::const_iterator nn_itr = lootPlayerNonQuestNonFFAConditionalItems.find(lv.viewer->GetGUIDLow()); + if (nn_itr != lootPlayerNonQuestNonFFAConditionalItems.end()) { - for (QuestItemList::iterator ci = lv.conditionallist->begin() ; ci != lv.conditionallist->end(); ++ci) + QuestItemList *conditional_list = nn_itr->second; + for (QuestItemList::iterator ci = conditional_list->begin() ; ci != conditional_list->end(); ++ci) { LootItem &item = l.items[ci->index]; if (!ci->is_looted && !item.is_looted) @@ -765,7 +792,7 @@ void LootTemplate::LootGroup::AddEntry(LootStoreItem& item) } // Rolls an item from the group, returns NULL if all miss their chances -LootStoreItem const * LootTemplate::LootGroup::Roll() const +LootStoreItem const * LootTemplate::LootGroup::Roll(bool rate) const { if (!ExplicitlyChanced.empty()) // First explicitly chanced entries are checked { @@ -777,7 +804,8 @@ LootStoreItem const * LootTemplate::LootGroup::Roll() const return &ExplicitlyChanced[i]; ItemPrototype const *pProto = objmgr.GetItemPrototype(ExplicitlyChanced[i].itemid); - Roll -= ExplicitlyChanced[i].chance; + //float qualityMultiplier = pProto && rate ? sWorld.getRate(qualityToRate[pProto->Quality]) : 1.0f; + Roll -= ExplicitlyChanced[i].chance;// * qualityMultiplier; if (Roll < 0) return &ExplicitlyChanced[i]; } @@ -813,9 +841,9 @@ bool LootTemplate::LootGroup::HasQuestDropForPlayer(Player const * player) const } // Rolls an item from the group (if any takes its chance) and adds the item to the loot -void LootTemplate::LootGroup::Process(Loot& loot) const +void LootTemplate::LootGroup::Process(Loot& loot, bool rate) const { - LootStoreItem const * item = Roll(); + LootStoreItem const * item = Roll(rate); if (item != NULL) loot.AddItem(*item); } @@ -900,21 +928,21 @@ void LootTemplate::AddEntry(LootStoreItem& item) } // Rolls for every item in the template and adds the rolled items the the loot -void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) const +void LootTemplate::Process(Loot& loot, LootStore const& store, bool rate, uint8 groupId) const { if (groupId) // Group reference uses own processing of the group { if (groupId > Groups.size()) return; // Error message already printed at loading stage - Groups[groupId-1].Process(loot); + Groups[groupId-1].Process(loot,rate); return; } // Rolling non-grouped items for (LootStoreItemList::const_iterator i = Entries.begin() ; i != Entries.end() ; ++i ) { - if ( !i->Roll() ) + if (!i->Roll(rate)) continue; // Bad luck for the entry if (i->mincountOrRef < 0) // References processing @@ -925,7 +953,7 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) co continue; // Error message already printed at loading stage for (uint32 loop=0; loop < i->maxcount; ++loop )// Ref multiplicator - Referenced->Process(loot, store, i->group); // Ref processing + Referenced->Process(loot, store, rate, i->group); } else // Plain entries (not a reference, not grouped) loot.AddItem(*i); // Chance is already checked, just add @@ -933,7 +961,7 @@ void LootTemplate::Process(Loot& loot, LootStore const& store, uint8 groupId) co // Now processing groups for (LootGroups::const_iterator i = Groups.begin( ) ; i != Groups.end( ) ; ++i ) - i->Process(loot); + i->Process(loot,rate); } // True if template includes at least 1 quest drop entry @@ -995,7 +1023,7 @@ bool LootTemplate::HasQuestDropForPlayer(LootTemplateMap const& store, Player co // Now checking groups for (LootGroups::const_iterator i = Groups.begin(); i != Groups.end(); ++i ) - if (i->HasQuestDrop()) + if (i->HasQuestDropForPlayer(player)) return true; return false; @@ -1137,6 +1165,29 @@ void LoadLootTemplates_Item() LootTemplates_Item.ReportUnusedIds(ids_set); } +void LoadLootTemplates_Milling() +{ + LootIdSet ids_set; + LootTemplates_Milling.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) + { + ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i); + if(!proto) + continue; + + if((proto->BagFamily & BAG_FAMILY_MASK_HERBS)==0) + continue; + + if(ids_set.count(proto->ItemId)) + ids_set.erase(proto->ItemId); + } + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_Milling.ReportUnusedIds(ids_set); +} + void LoadLootTemplates_Pickpocketing() { LootIdSet ids_set, ids_setUsed; @@ -1170,9 +1221,17 @@ void LoadLootTemplates_Prospecting() // remove real entries and check existence loot for(uint32 i = 1; i < sItemStorage.MaxEntry; ++i ) - if(ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i)) - if(ids_set.count(proto->ItemId)) - ids_set.erase(proto->ItemId); + { + ItemPrototype const* proto = sItemStorage.LookupEntry<ItemPrototype>(i); + if(!proto) + continue; + + if((proto->BagFamily & BAG_FAMILY_MASK_MINING_SUPP)==0) + continue; + + if(ids_set.count(proto->ItemId)) + ids_set.erase(proto->ItemId); + } // output error for any still listed (not referenced from appropriate table) ids LootTemplates_Prospecting.ReportUnusedIds(ids_set); @@ -1186,8 +1245,17 @@ void LoadLootTemplates_QuestMail() // remove real entries and check existence loot ObjectMgr::QuestMap const& questMap = objmgr.GetQuestTemplates(); for(ObjectMgr::QuestMap::const_iterator itr = questMap.begin(); itr != questMap.end(); ++itr ) + { + if(!itr->second->GetRewMailTemplateId()) + continue; + if(ids_set.count(itr->first)) ids_set.erase(itr->first); + /* disabled reporting: some quest mails not include items + else + LootTemplates_QuestMail.ReportNotExistedId(itr->first); + */ + } // output error for any still listed (not referenced from appropriate table) ids LootTemplates_QuestMail.ReportUnusedIds(ids_set); @@ -1219,6 +1287,37 @@ void LoadLootTemplates_Skinning() LootTemplates_Skinning.ReportUnusedIds(ids_set); } +void LoadLootTemplates_Spell() +{ + LootIdSet ids_set; + LootTemplates_Spell.LoadAndCollectLootIds(ids_set); + + // remove real entries and check existence loot + for(uint32 spell_id = 1; spell_id < sSpellStore.GetNumRows(); ++spell_id) + { + SpellEntry const* spellInfo = sSpellStore.LookupEntry (spell_id); + if(!spellInfo) + continue; + + // possible cases + if( !IsLootCraftingSpell(spellInfo)) + continue; + + if(!ids_set.count(spell_id)) + { + // not report about not trainable spells (optionally supported by DB) except with SPELL_ATTR_EX2_UNK14 (clams) + // 61756 (Northrend Inscription Research (FAST QA VERSION) for example + if ((spellInfo->Attributes & SPELL_ATTR_UNK5) || (spellInfo->AttributesEx2 & SPELL_ATTR_EX2_UNK14)) + LootTemplates_Spell.ReportNotExistedId(spell_id); + } + else + ids_set.erase(spell_id); + } + + // output error for any still listed (not referenced from appropriate table) ids + LootTemplates_QuestMail.ReportUnusedIds(ids_set); +} + void LoadLootTemplates_Reference() { LootIdSet ids_set; @@ -1229,6 +1328,7 @@ void LoadLootTemplates_Reference() LootTemplates_Fishing.CheckLootRefs(&ids_set); LootTemplates_Gameobject.CheckLootRefs(&ids_set); LootTemplates_Item.CheckLootRefs(&ids_set); + LootTemplates_Milling.CheckLootRefs(&ids_set); LootTemplates_Pickpocketing.CheckLootRefs(&ids_set); LootTemplates_Skinning.CheckLootRefs(&ids_set); LootTemplates_Disenchant.CheckLootRefs(&ids_set); diff --git a/src/game/LootMgr.h b/src/game/LootMgr.h index 1cb02c29bfc..8f54bb3bee1 100644 --- a/src/game/LootMgr.h +++ b/src/game/LootMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -77,7 +77,7 @@ struct LootStoreItem group(_group), maxcount(_maxcount), conditionId(_conditionId), needs_quest(_chanceOrQuestChance < 0) {} - bool Roll() const; // Checks if the entry takes it's chance (at loot generation) + bool Roll(bool rate) const; // Checks if the entry takes it's chance (at loot generation) bool IsValid(LootStore const& store, uint32 entry) const; // Checks correctness of values }; @@ -129,7 +129,8 @@ typedef std::set<uint32> LootIdSet; class LootStore { public: - explicit LootStore(char const* name, char const* entryName) : m_name(name), m_entryName(entryName) {} + explicit LootStore(char const* name, char const* entryName, bool ratesAllowed) + : m_name(name), m_entryName(entryName), m_ratesAllowed(ratesAllowed) {} virtual ~LootStore() { Clear(); } void Verify() const; @@ -147,6 +148,7 @@ class LootStore char const* GetName() const { return m_name; } char const* GetEntryName() const { return m_entryName; } + bool IsRatesAllowed() const { return m_ratesAllowed; } protected: void LoadLootTable(); void Clear(); @@ -154,6 +156,7 @@ class LootStore LootTemplateMap m_LootTemplates; char const* m_name; char const* m_entryName; + bool m_ratesAllowed; }; class LootTemplate @@ -165,7 +168,7 @@ class LootTemplate // Adds an entry to the group (at loading stage) void AddEntry(LootStoreItem& item); // Rolls for every item in the template and adds the rolled items the the loot - void Process(Loot& loot, LootStore const& store, uint8 GroupId = 0) const; + void Process(Loot& loot, LootStore const& store, bool rate, uint8 GroupId = 0) const; // True if template includes at least 1 quest drop entry bool HasQuestDrop(LootTemplateMap const& store, uint8 GroupId = 0) const; @@ -207,19 +210,20 @@ class LootValidatorRefManager : public RefManager<Loot, LootValidatorRef> }; //===================================================== +struct LootView; + +ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li); +ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv); struct Loot { + friend ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv); + QuestItemMap const& GetPlayerQuestItems() const { return PlayerQuestItems; } QuestItemMap const& GetPlayerFFAItems() const { return PlayerFFAItems; } QuestItemMap const& GetPlayerNonQuestNonFFAConditionalItems() const { return PlayerNonQuestNonFFAConditionalItems; } - QuestItemList* FillFFALoot(Player* player); - QuestItemList* FillQuestLoot(Player* player); - QuestItemList* FillNonQuestNonFFAConditionalLoot(Player* player); - std::vector<LootItem> items; - std::vector<LootItem> quest_items; uint32 gold; uint8 unlootedCount; @@ -264,13 +268,21 @@ struct Loot void RemoveLooter(uint64 GUID) { PlayersLooting.erase(GUID); } void generateMoneyLoot(uint32 minAmount, uint32 maxAmount); - void FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner); + void FillLoot(uint32 loot_id, LootStore const& store, Player* loot_owner, bool personal); // Inserts the item into the loot (called by LootTemplate processors) void AddItem(LootStoreItem const & item); LootItem* LootItemInSlot(uint32 lootslot, Player* player, QuestItem** qitem = NULL, QuestItem** ffaitem = NULL, QuestItem** conditem = NULL); + uint32 GetMaxSlotInLootFor(Player* player) const; + private: + void FillNotNormalLootFor(Player* player); + QuestItemList* FillFFALoot(Player* player); + QuestItemList* FillQuestLoot(Player* player); + QuestItemList* FillNonQuestNonFFAConditionalLoot(Player* player); + + std::vector<LootItem> quest_items; std::set<uint64> PlayersLooting; QuestItemMap PlayerQuestItems; QuestItemMap PlayerFFAItems; @@ -278,40 +290,41 @@ struct Loot // All rolls are registered here. They need to know, when the loot is not valid anymore LootValidatorRefManager i_LootValidatorRefManager; - }; struct LootView { Loot &loot; - QuestItemList *qlist; - QuestItemList *ffalist; - QuestItemList *conditionallist; Player *viewer; PermissionTypes permission; - LootView(Loot &_loot, QuestItemList *_qlist, QuestItemList *_ffalist, QuestItemList *_conditionallist, Player *_viewer,PermissionTypes _permission = ALL_PERMISSION) - : loot(_loot), qlist(_qlist), ffalist(_ffalist), conditionallist(_conditionallist), viewer(_viewer), permission(_permission) {} + LootView(Loot &_loot, Player *_viewer,PermissionTypes _permission = ALL_PERMISSION) + : loot(_loot), viewer(_viewer), permission(_permission) {} }; extern LootStore LootTemplates_Creature; extern LootStore LootTemplates_Fishing; extern LootStore LootTemplates_Gameobject; extern LootStore LootTemplates_Item; +extern LootStore LootTemplates_Milling; extern LootStore LootTemplates_Pickpocketing; extern LootStore LootTemplates_Skinning; extern LootStore LootTemplates_Disenchant; extern LootStore LootTemplates_Prospecting; extern LootStore LootTemplates_QuestMail; +extern LootStore LootTemplates_Spell; void LoadLootTemplates_Creature(); void LoadLootTemplates_Fishing(); void LoadLootTemplates_Gameobject(); void LoadLootTemplates_Item(); +void LoadLootTemplates_Milling(); void LoadLootTemplates_Pickpocketing(); void LoadLootTemplates_Skinning(); void LoadLootTemplates_Disenchant(); void LoadLootTemplates_Prospecting(); void LoadLootTemplates_QuestMail(); + +void LoadLootTemplates_Spell(); void LoadLootTemplates_Reference(); inline void LoadLootTables() @@ -320,14 +333,15 @@ inline void LoadLootTables() LoadLootTemplates_Fishing(); LoadLootTemplates_Gameobject(); LoadLootTemplates_Item(); + LoadLootTemplates_Milling(); LoadLootTemplates_Pickpocketing(); LoadLootTemplates_Skinning(); LoadLootTemplates_Disenchant(); LoadLootTemplates_Prospecting(); LoadLootTemplates_QuestMail(); + LoadLootTemplates_Spell(); + LoadLootTemplates_Reference(); } -ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li); -ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv); #endif diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 48bf94c4411..a699d9acc4d 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -601,7 +601,7 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data ) data << (uint32) (*itr)->mailTemplateId; // mail template (MailTemplate.dbc) data << (*itr)->subject; // Subject string - once 00, when mail type = 3 - data << (uint8) item_count; + data << (uint8) item_count; // client limit is 0x10 for(uint8 i = 0; i < item_count; ++i) { @@ -612,7 +612,7 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data ) data << (uint32) (item ? item->GetGUIDLow() : 0); // entry data << (uint32) (item ? item->GetEntry() : 0); - for(uint8 j = 0; j < 6; ++j) + for(uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j) { // unsure data << (uint32) (item ? item->GetEnchantmentCharges((EnchantmentSlot)j) : 0); @@ -626,13 +626,15 @@ void WorldSession::HandleGetMail(WorldPacket & recv_data ) // unk data << (uint32) (item ? item->GetItemSuffixFactor() : 0); // stack count - data << (uint8) (item ? item->GetCount() : 0); + data << (uint32) (item ? item->GetCount() : 0); // charges data << (uint32) (item ? item->GetSpellCharges() : 0); // durability data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY) : 0); // durability data << (uint32) (item ? item->GetUInt32Value(ITEM_FIELD_DURABILITY) : 0); + // unknown wotlk + data << (uint8) 0; } mails_count += 1; diff --git a/src/game/Mail.h b/src/game/Mail.h index f937c357325..ee4f6e54c4b 100644 --- a/src/game/Mail.h +++ b/src/game/Mail.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Makefile.am b/src/game/Makefile.am index ec9cbab40cb..6107a75f20e 100644 --- a/src/game/Makefile.am +++ b/src/game/Makefile.am @@ -1,6 +1,6 @@ -# Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> # -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -9,297 +9,304 @@ # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Process this file with automake to produce Makefile.in ## Sub-directories to parse ## CPP flags for includes, defines, etc. -AM_CPPFLAGS = +AM_CPPFLAGS = $(TRINI_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../dep/include -I$(srcdir)/../framework -I$(srcdir)/../shared -I$(srcdir)/../shared/vmap -I$(srcdir)/../realmd -DSYSCONFDIR=\"$(sysconfdir)/\" ## Build MaNGOS game library as convenience library. # All libraries will be convenience libraries. Might be changed to shared # later. -noinst_LIBRARIES = libgame.a - -libgame_a_CPPFLAGS = \ -$(MYSQL_INCLUDES) \ -$(POSTGRE_INCLUDES) \ -$(TRINI_INCLUDES) \ --I$(top_srcdir)/dep/include \ --I$(top_srcdir)/src/framework \ --I$(top_srcdir)/src/shared \ --I$(top_srcdir)/src/shared/vmap +noinst_LIBRARIES = libmangosgame.a # libmangossgame library will later be reused by ... -libgame_a_SOURCES = \ -$(srcdir)/AccountMgr.cpp \ -$(srcdir)/AccountMgr.h \ -$(srcdir)/AddonHandler.cpp \ -$(srcdir)/AddonHandler.h \ -$(srcdir)/AggressorAI.cpp \ -$(srcdir)/AggressorAI.h \ -$(srcdir)/AnimalRandomMovementGenerator.h \ -$(srcdir)/ArenaTeam.cpp \ -$(srcdir)/ArenaTeam.h \ -$(srcdir)/ArenaTeamHandler.cpp \ -$(srcdir)/AuctionHouse.cpp \ -$(srcdir)/AuctionHouseBot.cpp \ -$(srcdir)/AuctionHouseBot.h \ -$(srcdir)/AuctionHouseObject.h \ -$(srcdir)/Bag.cpp \ -$(srcdir)/Bag.h \ -$(srcdir)/BattleGround.cpp \ -$(srcdir)/BattleGroundAA.cpp \ -$(srcdir)/BattleGroundAB.cpp \ -$(srcdir)/BattleGroundAV.cpp \ -$(srcdir)/BattleGroundBE.cpp \ -$(srcdir)/BattleGroundEY.cpp \ -$(srcdir)/BattleGroundNA.cpp \ -$(srcdir)/BattleGroundRL.cpp \ -$(srcdir)/BattleGroundWS.cpp \ -$(srcdir)/BattleGround.h \ -$(srcdir)/BattleGroundAA.h \ -$(srcdir)/BattleGroundAB.h \ -$(srcdir)/BattleGroundAV.h \ -$(srcdir)/BattleGroundBE.h \ -$(srcdir)/BattleGroundEY.h \ -$(srcdir)/BattleGroundNA.h \ -$(srcdir)/BattleGroundRL.h \ -$(srcdir)/BattleGroundWS.h \ -$(srcdir)/BattleGroundHandler.cpp \ -$(srcdir)/BattleGroundMgr.cpp \ -$(srcdir)/BattleGroundMgr.h \ -$(srcdir)/Cell.h \ -$(srcdir)/CellImpl.h \ -$(srcdir)/Channel.cpp \ -$(srcdir)/Channel.h \ -$(srcdir)/ChannelHandler.cpp \ -$(srcdir)/ChannelMgr.h \ -$(srcdir)/CharacterHandler.cpp \ -$(srcdir)/Chat.cpp \ -$(srcdir)/Chat.h \ -$(srcdir)/ChatHandler.cpp \ -$(srcdir)/CombatHandler.cpp \ -$(srcdir)/ConfusedMovementGenerator.cpp \ -$(srcdir)/ConfusedMovementGenerator.h \ -$(srcdir)/Corpse.cpp \ -$(srcdir)/Corpse.h \ -$(srcdir)/CreatureAI.cpp \ -$(srcdir)/CreatureAI.h \ -$(srcdir)/CreatureAIImpl.h \ -$(srcdir)/CreatureAIRegistry.cpp \ -$(srcdir)/CreatureAIRegistry.h \ -$(srcdir)/CreatureAISelector.cpp \ -$(srcdir)/CreatureAISelector.h \ -$(srcdir)/CreatureGroups.cpp \ -$(srcdir)/CreatureGroups.h \ -$(srcdir)/Creature.cpp \ -$(srcdir)/Creature.h \ -$(srcdir)/Debugcmds.cpp \ -$(srcdir)/DestinationHolder.cpp \ -$(srcdir)/DestinationHolder.h \ -$(srcdir)/DestinationHolderImp.h \ -$(srcdir)/DuelHandler.cpp \ -$(srcdir)/DynamicObject.cpp \ -$(srcdir)/DynamicObject.h \ -$(srcdir)/FleeingMovementGenerator.cpp \ -$(srcdir)/FleeingMovementGenerator.h \ -$(srcdir)/Formulas.h \ -$(srcdir)/GameEvent.cpp \ -$(srcdir)/GameEvent.h \ -$(srcdir)/GameObject.cpp \ -$(srcdir)/GameObject.h \ -$(srcdir)/GlobalEvents.cpp \ -$(srcdir)/GlobalEvents.h \ -$(srcdir)/GossipDef.cpp \ -$(srcdir)/GossipDef.h \ -$(srcdir)/GridDefines.h \ -$(srcdir)/GridNotifiers.cpp \ -$(srcdir)/GridNotifiers.h \ -$(srcdir)/GridNotifiersImpl.h \ -$(srcdir)/GridStates.cpp \ -$(srcdir)/GridStates.h \ -$(srcdir)/Group.cpp \ -$(srcdir)/Group.h \ -$(srcdir)/GroupHandler.cpp \ -$(srcdir)/GuardAI.cpp \ -$(srcdir)/GuardAI.h \ -$(srcdir)/Guild.cpp \ -$(srcdir)/Guild.h \ -$(srcdir)/GuildHandler.cpp \ -$(srcdir)/HomeMovementGenerator.cpp \ -$(srcdir)/HomeMovementGenerator.h \ -$(srcdir)/HostilRefManager.cpp \ -$(srcdir)/HostilRefManager.h \ -$(srcdir)/IdleMovementGenerator.cpp \ -$(srcdir)/IdleMovementGenerator.h \ -$(srcdir)/InstanceData.cpp \ -$(srcdir)/InstanceData.h \ -$(srcdir)/InstanceSaveMgr.cpp \ -$(srcdir)/InstanceSaveMgr.h \ -$(srcdir)/Item.cpp \ -$(srcdir)/Item.h \ -$(srcdir)/ItemEnchantmentMgr.cpp \ -$(srcdir)/ItemEnchantmentMgr.h \ -$(srcdir)/ItemHandler.cpp \ -$(srcdir)/ItemPrototype.h \ -$(srcdir)/Language.h \ -$(srcdir)/Level0.cpp \ -$(srcdir)/Level1.cpp \ -$(srcdir)/Level2.cpp \ -$(srcdir)/Level3.cpp \ -$(srcdir)/LFGHandler.cpp \ -$(srcdir)/LootHandler.cpp \ -$(srcdir)/LootMgr.cpp \ -$(srcdir)/LootMgr.h \ -$(srcdir)/Mail.cpp \ -$(srcdir)/Mail.h \ -$(srcdir)/Map.cpp \ -$(srcdir)/Map.h \ -$(srcdir)/MapInstanced.cpp \ -$(srcdir)/MapInstanced.h \ -$(srcdir)/MapManager.cpp \ -$(srcdir)/MapManager.h \ -$(srcdir)/MiscHandler.cpp \ -$(srcdir)/MotionMaster.cpp \ -$(srcdir)/MotionMaster.h \ -$(srcdir)/MovementGenerator.cpp \ -$(srcdir)/MovementGenerator.h \ -$(srcdir)/MovementGeneratorImpl.h \ -$(srcdir)/MovementHandler.cpp \ -$(srcdir)/NPCHandler.cpp \ -$(srcdir)/NPCHandler.h \ -$(srcdir)/NullCreatureAI.cpp \ -$(srcdir)/NullCreatureAI.h \ -$(srcdir)/ObjectAccessor.cpp \ -$(srcdir)/ObjectAccessor.h \ -$(srcdir)/Object.cpp \ -$(srcdir)/ObjectDefines.h \ -$(srcdir)/ObjectGridLoader.cpp \ -$(srcdir)/ObjectGridLoader.h \ -$(srcdir)/Object.h \ -$(srcdir)/ObjectMgr.cpp \ -$(srcdir)/ObjectMgr.h \ -$(srcdir)/Opcodes.cpp \ -$(srcdir)/Opcodes.h \ -$(srcdir)/OutdoorPvP.cpp \ -$(srcdir)/OutdoorPvP.h \ -$(srcdir)/OutdoorPvPEP.cpp \ -$(srcdir)/OutdoorPvPEP.h \ -$(srcdir)/OutdoorPvPHP.cpp \ -$(srcdir)/OutdoorPvPHP.h \ -$(srcdir)/OutdoorPvPMgr.cpp \ -$(srcdir)/OutdoorPvPMgr.h \ -$(srcdir)/OutdoorPvPNA.cpp \ -$(srcdir)/OutdoorPvPNA.h \ -$(srcdir)/OutdoorPvPObjectiveAI.cpp \ -$(srcdir)/OutdoorPvPObjectiveAI.h \ -$(srcdir)/OutdoorPvPSI.cpp \ -$(srcdir)/OutdoorPvPSI.h \ -$(srcdir)/OutdoorPvPTF.cpp \ -$(srcdir)/OutdoorPvPTF.h \ -$(srcdir)/OutdoorPvPZM.cpp \ -$(srcdir)/OutdoorPvPZM.h \ -$(srcdir)/Path.h \ -$(srcdir)/PetAI.cpp \ -$(srcdir)/PetAI.h \ -$(srcdir)/Pet.cpp \ -$(srcdir)/Pet.h \ -$(srcdir)/PetHandler.cpp \ -$(srcdir)/PetitionsHandler.cpp \ -$(srcdir)/Player.cpp \ -$(srcdir)/Player.h \ -$(srcdir)/PlayerDump.cpp \ -$(srcdir)/PlayerDump.h \ -$(srcdir)/PointMovementGenerator.cpp \ -$(srcdir)/PointMovementGenerator.h \ -$(srcdir)/PossessedAI.cpp \ -$(srcdir)/PossessedAI.h \ -$(srcdir)/QueryHandler.cpp \ -$(srcdir)/QuestDef.cpp \ -$(srcdir)/QuestDef.h \ -$(srcdir)/QuestHandler.cpp \ -$(srcdir)/RandomMovementGenerator.cpp \ -$(srcdir)/RandomMovementGenerator.h \ -$(srcdir)/ReactorAI.cpp \ -$(srcdir)/ReactorAI.h \ -$(srcdir)/ScriptCalls.cpp \ -$(srcdir)/ScriptCalls.h \ -$(srcdir)/SharedDefines.h \ -$(srcdir)/SkillHandler.cpp \ -$(srcdir)/SpellAuraDefines.h \ -$(srcdir)/SpellAuras.cpp \ -$(srcdir)/SpellAuras.h \ -$(srcdir)/Spell.cpp \ -$(srcdir)/SpellEffects.cpp \ -$(srcdir)/Spell.h \ -$(srcdir)/SkillDiscovery.cpp \ -$(srcdir)/SkillDiscovery.h \ -$(srcdir)/SkillExtraItems.cpp \ -$(srcdir)/SkillExtraItems.h \ -$(srcdir)/SpellHandler.cpp \ -$(srcdir)/SocialMgr.cpp \ -$(srcdir)/SocialMgr.h \ -$(srcdir)/SpellMgr.cpp \ -$(srcdir)/SpellMgr.h \ -$(srcdir)/StatSystem.cpp \ -$(srcdir)/TargetedMovementGenerator.cpp \ -$(srcdir)/TargetedMovementGenerator.h \ -$(srcdir)/TaxiHandler.cpp \ -$(srcdir)/TemporarySummon.cpp \ -$(srcdir)/TemporarySummon.h \ -$(srcdir)/TicketHandler.cpp \ -$(srcdir)/TicketMgr.cpp \ -$(srcdir)/TicketMgr.h \ -$(srcdir)/Tools.cpp \ -$(srcdir)/Tools.h \ -$(srcdir)/TotemAI.cpp \ -$(srcdir)/TotemAI.h \ -$(srcdir)/Totem.cpp \ -$(srcdir)/Totem.h \ -$(srcdir)/TradeHandler.cpp \ -$(srcdir)/Transports.cpp \ -$(srcdir)/Transports.h \ -$(srcdir)/ThreatManager.cpp \ -$(srcdir)/ThreatManager.h \ -$(srcdir)/Traveller.h \ -$(srcdir)/Unit.cpp \ -$(srcdir)/Unit.h \ -$(srcdir)/UnitEvents.h \ -$(srcdir)/UpdateData.cpp \ -$(srcdir)/UpdateData.h \ -$(srcdir)/UpdateFields.h \ -$(srcdir)/UpdateMask.h \ -$(srcdir)/VoiceChatHandler.cpp \ -$(srcdir)/WaypointManager.cpp \ -$(srcdir)/WaypointManager.h \ -$(srcdir)/WaypointMovementGenerator.cpp \ -$(srcdir)/WaypointMovementGenerator.h \ -$(srcdir)/Weather.cpp \ -$(srcdir)/Weather.h \ -$(srcdir)/World.cpp \ -$(srcdir)/World.h \ -$(srcdir)/WorldLog.cpp \ -$(srcdir)/WorldLog.h \ -$(srcdir)/WorldSession.cpp \ -$(srcdir)/WorldSession.h \ -$(srcdir)/WorldSocket.cpp \ -$(srcdir)/WorldSocket.h \ -$(srcdir)/WorldSocketMgr.cpp \ -$(srcdir)/WorldSocketMgr.h \ -$(srcdir)/FollowerReference.cpp \ -$(srcdir)/FollowerReference.h \ -$(srcdir)/FollowerRefManager.h \ -$(srcdir)/GroupReference.cpp \ -$(srcdir)/GroupReference.h \ -$(srcdir)/GroupRefManager.h +libmangosgame_a_SOURCES = \ + AccountMgr.cpp \ + AccountMgr.h \ + AchievementMgr.h \ + AchievementMgr.cpp \ + AddonHandler.cpp \ + AddonHandler.h \ + AggressorAI.cpp \ + AggressorAI.h \ + AnimalRandomMovementGenerator.h \ + ArenaTeam.cpp \ + ArenaTeam.h \ + ArenaTeamHandler.cpp \ + AuctionHouse.cpp \ + AuctionHouseObject.h \ + Bag.cpp \ + Bag.h \ + BattleGround.cpp \ + BattleGroundAA.cpp \ + BattleGroundAB.cpp \ + BattleGroundAV.cpp \ + BattleGroundBE.cpp \ + BattleGroundDS.cpp \ + BattleGroundEY.cpp \ + BattleGroundNA.cpp \ + BattleGroundRL.cpp \ + BattleGroundRV.cpp \ + BattleGroundSA.cpp \ + BattleGroundWS.cpp \ + BattleGround.h \ + BattleGroundAA.h \ + BattleGroundAB.h \ + BattleGroundAV.h \ + BattleGroundBE.h \ + BattleGroundDS.h \ + BattleGroundEY.h \ + BattleGroundNA.h \ + BattleGroundRL.h \ + BattleGroundRV.h \ + BattleGroundSA.h \ + BattleGroundWS.h \ + BattleGroundHandler.cpp \ + BattleGroundMgr.cpp \ + BattleGroundMgr.h \ + Calendar.cpp \ + Calendar.h \ + CalendarHandler.cpp \ + Cell.h \ + CellImpl.h \ + Channel.cpp \ + Channel.h \ + ChannelHandler.cpp \ + ChannelMgr.h \ + CharacterHandler.cpp \ + Chat.cpp \ + Chat.h \ + ChatHandler.cpp \ + CombatHandler.cpp \ + ConfusedMovementGenerator.cpp \ + ConfusedMovementGenerator.h \ + Corpse.cpp \ + Corpse.h \ + CreatureAI.cpp \ + CreatureAI.h \ + CreatureAIImpl.h \ + CreatureAIRegistry.cpp \ + CreatureAIRegistry.h \ + CreatureAISelector.cpp \ + CreatureAISelector.h \ + CreatureGroups.cpp \ + CreatureGroups.h \ + Creature.cpp \ + Creature.h \ + debugcmds.cpp \ + DestinationHolder.cpp \ + DestinationHolder.h \ + DestinationHolderImp.h \ + DuelHandler.cpp \ + DynamicObject.cpp \ + DynamicObject.h \ + FleeingMovementGenerator.cpp \ + FleeingMovementGenerator.h \ + Formulas.h \ + GameEvent.cpp \ + GameEvent.h \ + GameObject.cpp \ + GameObject.h \ + GlobalEvents.cpp \ + GlobalEvents.h \ + GossipDef.cpp \ + GossipDef.h \ + GridDefines.h \ + GridNotifiers.cpp \ + GridNotifiers.h \ + GridNotifiersImpl.h \ + GridStates.cpp \ + GridStates.h \ + Group.cpp \ + Group.h \ + GroupHandler.cpp \ + GuardAI.cpp \ + GuardAI.h \ + Guild.cpp \ + Guild.h \ + GuildHandler.cpp \ + HomeMovementGenerator.cpp \ + HomeMovementGenerator.h \ + HostilRefManager.cpp \ + HostilRefManager.h \ + IdleMovementGenerator.cpp \ + IdleMovementGenerator.h \ + InstanceData.cpp \ + InstanceData.h \ + InstanceSaveMgr.cpp \ + InstanceSaveMgr.h \ + Item.cpp \ + Item.h \ + ItemEnchantmentMgr.cpp \ + ItemEnchantmentMgr.h \ + ItemHandler.cpp \ + ItemPrototype.h \ + Language.h \ + Level0.cpp \ + Level1.cpp \ + Level2.cpp \ + Level3.cpp \ + LFGHandler.cpp \ + LootHandler.cpp \ + LootMgr.cpp \ + LootMgr.h \ + Mail.cpp \ + Mail.h \ + Map.cpp \ + Map.h \ + MapInstanced.cpp \ + MapInstanced.h \ + MapManager.cpp \ + MapManager.h \ + MapReference.h \ + MapRefManager.h \ + MiscHandler.cpp \ + MotionMaster.cpp \ + MotionMaster.h \ + MovementGenerator.cpp \ + MovementGenerator.h \ + MovementGeneratorImpl.h \ + MovementHandler.cpp \ + NPCHandler.cpp \ + NPCHandler.h \ + NullCreatureAI.cpp \ + NullCreatureAI.h \ + ObjectAccessor.cpp \ + ObjectAccessor.h \ + Object.cpp \ + ObjectDefines.h \ + ObjectGridLoader.cpp \ + ObjectGridLoader.h \ + Object.h \ + ObjectMgr.cpp \ + ObjectMgr.h \ + ObjectPosSelector.cpp \ + ObjectPosSelector.h \ + Opcodes.cpp \ + Opcodes.h \ + OutdoorPvP.cpp \ + OutdoorPvP.h \ + OutdoorPvPEP.cpp \ + OutdoorPvPEP.h \ + OutdoorPvPHP.cpp \ + OutdoorPvPHP.h \ + OutdoorPvPMgr.cpp \ + OutdoorPvPMgr.h \ + OutdoorPvPNA.cpp \ + OutdoorPvPNA.h \ + OutdoorPvPObjectiveAI.cpp \ + OutdoorPvPObjectiveAI.h \ + OutdoorPvPSI.cpp \ + OutdoorPvPSI.h \ + OutdoorPvPTF.cpp \ + OutdoorPvPTF.h \ + OutdoorPvPZM.cpp \ + OutdoorPvPZM.h \ + Path.h \ + PetAI.cpp \ + PetAI.h \ + Pet.cpp \ + Pet.h \ + PetHandler.cpp \ + PetitionsHandler.cpp \ + Player.cpp \ + Player.h \ + PlayerDump.cpp \ + PlayerDump.h \ + PossessedAI.cpp \ + PossessedAI.h \ + PointMovementGenerator.cpp \ + PointMovementGenerator.h \ + QueryHandler.cpp \ + QuestDef.cpp \ + QuestDef.h \ + QuestHandler.cpp \ + RandomMovementGenerator.cpp \ + RandomMovementGenerator.h \ + ReactorAI.cpp \ + ReactorAI.h \ + ScriptCalls.cpp \ + ScriptCalls.h \ + SharedDefines.h \ + SkillHandler.cpp \ + SpellAuraDefines.h \ + SpellAuras.cpp \ + SpellAuras.h \ + Spell.cpp \ + SpellEffects.cpp \ + Spell.h \ + SkillDiscovery.cpp \ + SkillDiscovery.h \ + SkillExtraItems.cpp \ + SkillExtraItems.h \ + SpellHandler.cpp \ + SocialMgr.cpp \ + SocialMgr.h \ + SpellMgr.cpp \ + SpellMgr.h \ + StatSystem.cpp \ + TargetedMovementGenerator.cpp \ + TargetedMovementGenerator.h \ + TaxiHandler.cpp \ + TemporarySummon.cpp \ + TemporarySummon.h \ + TotemAI.cpp \ + TotemAI.h \ + Totem.cpp \ + Totem.h \ + TradeHandler.cpp \ + Transports.cpp \ + Transports.h \ + ThreatManager.cpp \ + ThreatManager.h \ + TicketHandler.cpp \ + TicketMgr.cpp \ + TicketMgr.h \ + Traveller.h \ + Unit.cpp \ + Unit.h \ + UnitEvents.h \ + UpdateData.cpp \ + UpdateData.h \ + UpdateFields.h \ + UpdateMask.h \ + Vehicle.cpp \ + Vehicle.h \ + VoiceChatHandler.cpp \ + WaypointManager.cpp \ + WaypointManager.h \ + WaypointMovementGenerator.cpp \ + WaypointMovementGenerator.h \ + Weather.cpp \ + Weather.h \ + World.cpp \ + World.h \ + WorldLog.cpp \ + WorldLog.h \ + WorldSession.cpp \ + WorldSession.h \ + WorldSocket.cpp \ + WorldSocket.h \ + WorldSocketMgr.cpp \ + WorldSocketMgr.h \ + FollowerReference.cpp \ + FollowerReference.h \ + FollowerRefManager.h \ + GroupReference.cpp \ + GroupReference.h \ + GroupRefManager.h + +## Link against shared library +libmangosgame_a_LIBADD = ../shared/libmangosshared.a ../shared/Auth/libmangosauth.a ../shared/Config/libmangosconfig.a ../shared/Database/libmangosdatabase.a ../shared/vmap/libmangosvmaps.a ## Additional files to include when running 'make dist' # Nothing yet. diff --git a/src/game/Map.cpp b/src/game/Map.cpp index dd62f1e1c9f..40df012410b 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,7 +45,7 @@ #define MAX_GRID_LOAD_TIME 50 // magic *.map header -const char MAP_MAGIC[] = "MAP_2.00"; +const char MAP_MAGIC[] = "MAP_2.01"; GridState* si_GridStates[MAX_GRID_STATE]; @@ -257,7 +257,7 @@ template<> void Map::AddToGrid(Creature* obj, NGridType *grid, Cell const& cell) { // add to world object registry in grid - if(obj->isPet() /*&& IS_PLAYER_GUID(obj->GetOwnerGUID())*/ || obj->isPossessedByPlayer()) + if(obj->isPet() || obj->isPossessedByPlayer() || obj->isVehicle()) { (*grid)(cell.CellX(), cell.CellY()).AddWorldObject<Creature>(obj, obj->GetGUID()); obj->SetCurrentCell(cell); @@ -301,7 +301,7 @@ template<> void Map::RemoveFromGrid(Creature* obj, NGridType *grid, Cell const& cell) { // remove from world object registry in grid - if(obj->isPet() || obj->isPossessedByPlayer()) + if(obj->isPet() || obj->isPossessedByPlayer() || obj->isVehicle()) { (*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject<Creature>(obj, obj->GetGUID()); } @@ -1289,7 +1289,7 @@ float Map::GetVmapHeight(float x, float y, float z, bool useMaps) const return vmapHeight; } -uint16 Map::GetAreaFlag(float x, float y ) const +uint16 Map::GetAreaFlag(float x, float y, float z) const { //local x,y coords float lx,ly; @@ -1307,11 +1307,30 @@ uint16 Map::GetAreaFlag(float x, float y ) const // ensure GridMap is loaded const_cast<Map*>(this)->EnsureGridCreated(GridPair(63-gx,63-gy)); + uint16 areaflag; if(GridMaps[gx][gy]) - return GridMaps[gx][gy]->area_flag[(int)(lx)][(int)(ly)]; + areaflag = GridMaps[gx][gy]->area_flag[(int)(lx)][(int)(ly)]; // this used while not all *.map files generated (instances) else - return GetAreaFlagByMapId(i_id); + areaflag = GetAreaFlagByMapId(i_id); + + //FIXME: some hacks for areas above or underground for ground area + // required for area specific spells/etc, until map/vmap data + // not provided correct areaflag with this hacks + switch(areaflag) + { + // Acherus: The Ebon Hold (Plaguelands: The Scarlet Enclave) + case 1984: // Plaguelands: The Scarlet Enclave + case 2076: // Death's Breach (Plaguelands: The Scarlet Enclave) + case 2745: // The Noxious Pass (Plaguelands: The Scarlet Enclave) + if(z > 350.0f) areaflag = 2048; break; + // Acherus: The Ebon Hold (Eastern Plaguelands) + case 856: // The Noxious Glade (Eastern Plaguelands) + case 2456: // Death's Breach (Eastern Plaguelands) + if(z > 350.0f) areaflag = 1950; break; + } + + return areaflag; } uint8 Map::GetTerrainType(float x, float y ) const @@ -1752,10 +1771,10 @@ bool InstanceMap::CanEnter(Player *player) } // cannot enter if the instance is full (player cap), GMs don't count - InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId()); - if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= iTemplate->maxPlayers) + uint32 maxPlayers = GetMaxPlayers(); + if (!player->isGameMaster() && GetPlayersCountExceptGMs() >= maxPlayers) { - sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), iTemplate->maxPlayers, player->GetName()); + sLog.outDetail("MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName()); player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS); return false; } @@ -2065,6 +2084,14 @@ void InstanceMap::SetResetSchedule(bool on) } } +uint32 InstanceMap::GetMaxPlayers() const +{ + InstanceTemplate const* iTemplate = objmgr.GetInstanceTemplate(GetId()); + if(!iTemplate) + return 0; + return IsHeroic() ? iTemplate->maxPlayersHeroic : iTemplate->maxPlayers; +} + /* ******* Battleground Instance Maps ******* */ BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId) @@ -2120,12 +2147,14 @@ void BattleGroundMap::UnloadAll(bool pForce) { while(HavePlayers()) { - Player * plr = m_mapRefManager.getFirst()->getSource(); - if(plr) (plr)->TeleportTo(plr->m_homebindMapId, plr->m_homebindX, plr->m_homebindY, plr->m_homebindZ, plr->GetOrientation()); - // TeleportTo removes the player from this map (if the map exists) -> calls BattleGroundMap::Remove -> invalidates the iterator. - // just in case, remove the player from the list explicitly here as well to prevent a possible infinite loop - // note that this remove is not needed if the code works well in other places - plr->GetMapRef().unlink(); + if(Player * plr = m_mapRefManager.getFirst()->getSource()) + { + plr->TeleportTo(plr->GetBattleGroundEntryPoint()); + // TeleportTo removes the player from this map (if the map exists) -> calls BattleGroundMap::Remove -> invalidates the iterator. + // just in case, remove the player from the list explicitly here as well to prevent a possible infinite loop + // note that this remove is not needed if the code works well in other places + plr->GetMapRef().unlink(); + } } Map::UnloadAll(pForce); diff --git a/src/game/Map.h b/src/game/Map.h index 0c26fb36a00..92274932362 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -100,7 +100,8 @@ struct InstanceTemplate uint32 levelMin; uint32 levelMax; uint32 maxPlayers; - uint32 reset_delay; + uint32 maxPlayersHeroic; + uint32 reset_delay; // FIX ME: now exist normal/heroic raids with possible different time of reset. float startLocX; float startLocY; float startLocZ; @@ -135,10 +136,8 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O // currently unused for normal maps bool CanUnload(uint32 diff) { - if(!m_unloadTimer) - return false; - if(m_unloadTimer <= diff) - return true; + if(!m_unloadTimer) return false; + if(m_unloadTimer <= diff) return true; m_unloadTimer -= diff; return false; } @@ -160,7 +159,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O template<class LOCK_TYPE, class T, class CONTAINER> void Visit(const CellLock<LOCK_TYPE> &cell, TypeContainerVisitor<T, CONTAINER> &visitor); - inline bool IsRemovalGrid(float x, float y) const + bool IsRemovalGrid(float x, float y) const { GridPair p = Trinity::ComputeGridPair(x, y); return( !getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL ); @@ -194,7 +193,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O float GetVmapHeight(float x, float y, float z, bool useMaps) const; bool IsInWater(float x, float y, float z) const; // does not use z pos. This is for future use - uint16 GetAreaFlag(float x, float y ) const; + uint16 GetAreaFlag(float x, float y, float z) const; uint8 GetTerrainType(float x, float y ) const; float GetWaterLevel(float x, float y ) const; bool IsUnderWater(float x, float y, float z) const; @@ -202,14 +201,14 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O static uint32 GetAreaId(uint16 areaflag,uint32 map_id); static uint32 GetZoneId(uint16 areaflag,uint32 map_id); - uint32 GetAreaId(float x, float y) const + uint32 GetAreaId(float x, float y, float z) const { - return GetAreaId(GetAreaFlag(x,y),i_id); + return GetAreaId(GetAreaFlag(x,y,z),i_id); } - uint32 GetZoneId(float x, float y) const + uint32 GetZoneId(float x, float y, float z) const { - return GetZoneId(GetAreaFlag(x,y),i_id); + return GetZoneId(GetAreaFlag(x,y,z),i_id); } virtual void MoveAllCreaturesInMoveList(); @@ -233,6 +232,17 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); } bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); } bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); } + bool GetEntrancePos(int32 &mapid, float &x, float &y) + { + if(!i_mapEntry) + return false; + if(i_mapEntry->entrance_map < 0) + return false; + mapid = i_mapEntry->entrance_map; + x = i_mapEntry->entrance_x; + y = i_mapEntry->entrance_y; + return true; + } void AddObjectToRemoveList(WorldObject *obj); void DoDelayedMovesAndRemoves(); @@ -304,7 +314,7 @@ class TRINITY_DLL_SPEC Map : public GridRefManager<NGridType>, public Trinity::O bool isGridObjectDataLoaded(uint32 x, uint32 y) const { return getNGrid(x,y)->isGridObjectDataLoaded(); } void setGridObjectDataLoaded(bool pLoaded, uint32 x, uint32 y) { getNGrid(x,y)->setGridObjectDataLoaded(pLoaded); } - inline void setNGrid(NGridType* grid, uint32 x, uint32 y); + void setNGrid(NGridType* grid, uint32 x, uint32 y); void UpdateActiveCells(const float &x, const float &y, const uint32 &t_diff); protected: @@ -375,6 +385,7 @@ class TRINITY_DLL_SPEC InstanceMap : public Map bool CanEnter(Player* player); void SendResetWarnings(uint32 timeLeft) const; void SetResetSchedule(bool on); + uint32 GetMaxPlayers() const; private: bool m_resetAfterUnload; bool m_unloadWhenEmpty; diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp index 841d366b6c5..c61ed531c9a 100644 --- a/src/game/MapInstanced.cpp +++ b/src/game/MapInstanced.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/MapInstanced.h b/src/game/MapInstanced.h index cde37f9f3ff..924f77b8d82 100644 --- a/src/game/MapInstanced.h +++ b/src/game/MapInstanced.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp index fdd62d2d4ce..d159b1a6265 100644 --- a/src/game/MapManager.cpp +++ b/src/game/MapManager.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -175,7 +175,8 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player) //The player has a heroic mode and tries to enter into instance which has no a heroic mode if (!entry->SupportsHeroicMode() && player->GetDifficulty() == DIFFICULTY_HEROIC) { - player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY2); //Send aborted message + //Send aborted message + player->SendTransferAborted(mapid, TRANSFER_ABORT_DIFFICULTY, DIFFICULTY_HEROIC); return false; } @@ -240,7 +241,7 @@ void MapManager::RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y) } void -MapManager::Update(time_t diff) +MapManager::Update(uint32 diff) { i_timer.Update(diff); if( !i_timer.Passed() ) @@ -286,7 +287,8 @@ bool MapManager::ExistMapAndVMap(uint32 mapid, float x,float y) bool MapManager::IsValidMAP(uint32 mapid) { MapEntry const* mEntry = sMapStore.LookupEntry(mapid); - return mEntry && (!mEntry->Instanceable() || objmgr.GetInstanceTemplate(mapid)); + return mEntry && (!mEntry->IsDungeon() || objmgr.GetInstanceTemplate(mapid)); + // TODO: add check for battleground template } void MapManager::LoadGrid(int mapid, float x, float y, const WorldObject* obj, bool no_unload) diff --git a/src/game/MapManager.h b/src/game/MapManager.h index cba0a86d1a5..8d4b2ba8885 100644 --- a/src/game/MapManager.h +++ b/src/game/MapManager.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,18 +47,18 @@ class TRINITY_DLL_DECL MapManager : public Trinity::Singleton<MapManager, Trinit Map const* GetBaseMap(uint32 id) const { return const_cast<MapManager*>(this)->_GetBaseMap(id); } void DeleteInstance(uint32 mapid, uint32 instanceId); - inline uint16 GetAreaFlag(uint32 mapid, float x, float y) const + uint16 GetAreaFlag(uint32 mapid, float x, float y, float z) const { Map const* m = GetBaseMap(mapid); - return m->GetAreaFlag(x, y); + return m->GetAreaFlag(x, y, z); } - inline uint32 GetAreaId(uint32 mapid, float x, float y) { return Map::GetAreaId(GetAreaFlag(mapid, x, y),mapid); } - inline uint32 GetZoneId(uint32 mapid, float x, float y) { return Map::GetZoneId(GetAreaFlag(mapid, x, y),mapid); } + uint32 GetAreaId(uint32 mapid, float x, float y, float z) const { return Map::GetAreaId(GetAreaFlag(mapid, x, y, z),mapid); } + uint32 GetZoneId(uint32 mapid, float x, float y, float z) const { return Map::GetZoneId(GetAreaFlag(mapid, x, y, z),mapid); } void Initialize(void); - void Update(time_t); + void Update(uint32); - inline void SetGridCleanUpDelay(uint32 t) + void SetGridCleanUpDelay(uint32 t) { if( t < MIN_GRID_DELAY ) i_gridCleanUpDelay = MIN_GRID_DELAY; @@ -66,7 +66,7 @@ class TRINITY_DLL_DECL MapManager : public Trinity::Singleton<MapManager, Trinit i_gridCleanUpDelay = t; } - inline void SetMapUpdateInterval(uint32 t) + void SetMapUpdateInterval(uint32 t) { if( t > MIN_MAP_UPDATE_DELAY ) t = MIN_MAP_UPDATE_DELAY; @@ -96,6 +96,11 @@ class TRINITY_DLL_DECL MapManager : public Trinity::Singleton<MapManager, Trinit return IsValidMAP(mapid) && Trinity::IsValidMapCoord(x,y,z,o); } + static bool IsValidMapCoord(WorldLocation const& loc) + { + return IsValidMapCoord(loc.mapid,loc.x,loc.y,loc.z,loc.o); + } + void DoDelayedMovesAndRemoves(); void LoadTransports(); @@ -108,7 +113,7 @@ class TRINITY_DLL_DECL MapManager : public Trinity::Singleton<MapManager, Trinit bool CanPlayerEnter(uint32 mapid, Player* player); void RemoveBonesFromMap(uint32 mapid, uint64 guid, float x, float y); - inline uint32 GenerateInstanceId() { return ++i_MaxInstanceId; } + uint32 GenerateInstanceId() { return ++i_MaxInstanceId; } void InitMaxInstanceId(); /* statistics */ diff --git a/src/game/MapRefManager.h b/src/game/MapRefManager.h index bfd0ca12eda..02f8b2ea465 100644 --- a/src/game/MapRefManager.h +++ b/src/game/MapRefManager.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/MapReference.h b/src/game/MapReference.h index 5300d1aa4a7..397eec0a06b 100644 --- a/src/game/MapReference.h +++ b/src/game/MapReference.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index a6b84d30de2..bae43ca26dc 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -306,13 +306,13 @@ void WorldSession::HandleLogoutRequestOpcode( WorldPacket & /*recv_data*/ ) // not set flags if player can't free move to prevent lost state at logout cancel if(GetPlayer()->CanFreeMove()) { - GetPlayer()->SetStandState(PLAYER_STATE_SIT); + GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT); WorldPacket data( SMSG_FORCE_MOVE_ROOT, (8+4) ); // guess size data.append(GetPlayer()->GetPackGUID()); data << (uint32)2; SendPacket( &data ); - GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } WorldPacket data( SMSG_LOGOUT_RESPONSE, 5 ); @@ -346,10 +346,10 @@ void WorldSession::HandleLogoutCancelOpcode( WorldPacket & /*recv_data*/ ) SendPacket( &data ); //! Stand Up - GetPlayer()->SetStandState(PLAYER_STATE_NONE); + GetPlayer()->SetStandState(UNIT_STAND_STATE_STAND); //! DISABLE_ROTATE - GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + GetPlayer()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } sLog.outDebug( "WORLD: sent SMSG_LOGOUT_CANCEL_ACK Message" ); @@ -363,10 +363,12 @@ void WorldSession::HandleTogglePvP( WorldPacket & recv_data ) bool newPvPStatus; recv_data >> newPvPStatus; GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP, newPvPStatus); + GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER, !newPvPStatus); } else { GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP); + GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER); } if(GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) @@ -816,7 +818,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) GetPlayer()->SetRestType(REST_TYPE_IN_TAVERN); if(sWorld.IsFFAPvPRealm()) - GetPlayer()->RemoveFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + GetPlayer()->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); return; } @@ -886,7 +888,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) if(missingItem) SendAreaTriggerMessage(GetTrinityString(LANG_LEVEL_MINREQUIRED_AND_ITEM), at->requiredLevel, objmgr.GetItemPrototype(missingItem)->Name1); else if(missingKey) - GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY2); + GetPlayer()->SendTransferAborted(at->target_mapId, TRANSFER_ABORT_DIFFICULTY, DIFFICULTY_HEROIC); else if(missingHeroicQuest) SendAreaTriggerMessage(at->heroicQuestFailedText.c_str()); else if(missingQuest) @@ -900,16 +902,96 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) GetPlayer()->TeleportTo(at->target_mapId,at->target_X,at->target_Y,at->target_Z,at->target_Orientation,TELE_TO_NOT_LEAVE_TRANSPORT); } -void WorldSession::HandleUpdateAccountData(WorldPacket &/*recv_data*/) +void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) { sLog.outDetail("WORLD: Received CMSG_UPDATE_ACCOUNT_DATA"); - //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 4+4+4); + + uint32 type, timestamp, decompressedSize; + recv_data >> type >> timestamp >> decompressedSize; + + sLog.outDebug("UAD: type %u, time %u, decompressedSize %u", type, timestamp, decompressedSize); + + if(type > NUM_ACCOUNT_DATA_TYPES) + return; + + if(decompressedSize == 0) // erase + { + SetAccountData(type, timestamp, ""); + + WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); + data << uint32(type); + data << uint32(0); + SendPacket(&data); + + return; + } + + if(decompressedSize > 0xFFFF) + { + sLog.outError("UAD: Account data packet too big, size %u", decompressedSize); + return; + } + + ByteBuffer dest; + dest.resize(decompressedSize); + + uLongf realSize = decompressedSize; + if(uncompress(const_cast<uint8*>(dest.contents()), &realSize, const_cast<uint8*>(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK) + { + sLog.outError("UAD: Failed to decompress account data"); + return; + } + + std::string adata; + dest >> adata; + + SetAccountData(type, timestamp, adata); + + WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); + data << uint32(type); + data << uint32(0); + SendPacket(&data); } -void WorldSession::HandleRequestAccountData(WorldPacket& /*recv_data*/) +void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) { sLog.outDetail("WORLD: Received CMSG_REQUEST_ACCOUNT_DATA"); - //recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 4); + + uint32 type; + recv_data >> type; + + sLog.outDebug("RAD: type %u", type); + + if(type > NUM_ACCOUNT_DATA_TYPES) + return; + + AccountData *adata = GetAccountData(type); + + uint32 size = adata->Data.size(); + + ByteBuffer dest; + dest.resize(size); + + uLongf destSize = size; + if(size && compress(const_cast<uint8*>(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK) + { + sLog.outDebug("RAD: Failed to compress account data"); + return; + } + + dest.resize(destSize); + + WorldPacket data (SMSG_UPDATE_ACCOUNT_DATA, 8+4+4+4+destSize); + data << uint64(_player->GetGUID()); // player guid + data << uint32(type); // type (0-7) + data << uint32(adata->Time); // unix time + data << uint32(size); // decompressed length + data.append(dest); // compressed data + SendPacket(&data); } void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recv_data) @@ -1441,11 +1523,11 @@ void WorldSession::HandleChooseTitleOpcode( WorldPacket & recv_data ) GetPlayer()->SetUInt32Value(PLAYER_CHOSEN_TITLE, title); } -void WorldSession::HandleAllowMoveAckOpcode( WorldPacket & recv_data ) +void WorldSession::HandleTimeSyncResp( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 4+4); - sLog.outDebug("CMSG_ALLOW_MOVE_ACK"); + sLog.outDebug("CMSG_TIME_SYNC_RESP"); uint32 counter, time_; recv_data >> counter >> time_; @@ -1515,26 +1597,6 @@ void WorldSession::HandleDungeonDifficultyOpcode( WorldPacket & recv_data ) } } -void WorldSession::HandleNewUnknownOpcode( WorldPacket & recv_data ) -{ - sLog.outDebug("New Unknown Opcode %u", recv_data.GetOpcode()); - recv_data.hexlike(); - /* - New Unknown Opcode 837 - STORAGE_SIZE: 60 - 02 00 00 00 00 00 00 00 | 00 00 00 00 01 20 00 00 - 89 EB 33 01 71 5C 24 C4 | 15 03 35 45 74 47 8B 42 - BA B8 1B 40 00 00 00 00 | 00 00 00 00 77 66 42 BF - 23 91 26 3F 00 00 60 41 | 00 00 00 00 - - New Unknown Opcode 837 - STORAGE_SIZE: 44 - 02 00 00 00 00 00 00 00 | 00 00 00 00 00 00 80 00 - 7B 80 34 01 84 EA 2B C4 | 5F A1 36 45 C9 39 1C 42 - BA B8 1B 40 CE 06 00 00 | 00 00 80 3F - */ -} - void WorldSession::HandleDismountOpcode( WorldPacket & /*recv_data*/ ) { sLog.outDebug("WORLD: CMSG_CANCEL_MOUNT_AURA"); @@ -1601,3 +1663,32 @@ void WorldSession::HandleSetTaxiBenchmarkOpcode( WorldPacket & recv_data ) sLog.outDebug("Client used \"/timetest %d\" command", mode); } + +void WorldSession::HandleSpellClick( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 8); + + uint64 guid; + recv_data >> guid; + + Vehicle *vehicle = ObjectAccessor::GetVehicle(guid); + + if(!vehicle) + return; + + _player->EnterVehicle(vehicle); +} + +void WorldSession::HandleInspectAchievements( WorldPacket & recv_data ) +{ + CHECK_PACKET_SIZE(recv_data, 1); + uint64 guid; + if(!recv_data.readPackGUID(guid)) + return; + + Player *player = objmgr.GetPlayer(guid); + if(!player) + return; + + player->GetAchievementMgr().SendRespondInspectAchievements(_player); +} diff --git a/src/game/MovementGenerator.cpp b/src/game/MovementGenerator.cpp index 3cfccdb81c7..a80f09c7204 100644 --- a/src/game/MovementGenerator.cpp +++ b/src/game/MovementGenerator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/MovementGenerator.h b/src/game/MovementGenerator.h index d362b6be648..554158129d6 100644 --- a/src/game/MovementGenerator.h +++ b/src/game/MovementGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/MovementGeneratorImpl.h b/src/game/MovementGeneratorImpl.h index 43c18ac6866..03b0c873f33 100644 --- a/src/game/MovementGeneratorImpl.h +++ b/src/game/MovementGeneratorImpl.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 8c808e3a53a..4e4dff56a47 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,6 +31,7 @@ #include "BattleGround.h" #include "WaypointMovementGenerator.h" #include "InstanceSaveMgr.h" +#include "ObjectMgr.h" void WorldSession::HandleMoveWorldportAckOpcode( WorldPacket & /*recv_data*/ ) { @@ -131,31 +132,23 @@ void WorldSession::HandleMoveWorldportAckOpcode() if(!mEntry->IsMountAllowed()) _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); - // battleground state prepare + // battleground state prepare (in case join to BG), at relogin/tele player not invited // only add to bg group and object, if the player was invited (else he entered through command) - if(_player->InBattleGround() && _player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) + if(_player->InBattleGround()) { - BattleGround *bg = _player->GetBattleGround(); - if(bg) + // cleanup seting if outdated + if(!mEntry->IsBattleGroundOrArena()) { - bg->AddPlayer(_player); - if(bg->GetMapId() == _player->GetMapId()) // we teleported to bg - { - // get the team this way, because arenas might 'override' the teams. - uint32 team = bg->GetPlayerTeam(_player->GetGUID()); - if(!team) - team = _player->GetTeam(); - if(!bg->GetBgRaid(team)) // first player joined - { - Group *group = new Group; - bg->SetBgRaid(team, group); - group->Create(_player->GetGUIDLow(), _player->GetName()); - } - else // raid already exist - { - bg->GetBgRaid(team)->AddMember(_player->GetGUID(), _player->GetName()); - } - } + // Do next only if found in battleground + _player->SetBattleGroundId(0); // We're not in BG. + // reset destination bg team + _player->SetBGTeam(0); + } + // join to bg case + else if(BattleGround *bg = _player->GetBattleGround()) + { + if(_player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) + bg->AddPlayer(_player); } } @@ -178,64 +171,15 @@ void WorldSession::HandleMoveWorldportAckOpcode() void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { - CHECK_PACKET_SIZE(recv_data, 4+1+4+4+4+4+4); + uint32 opcode = recv_data.GetOpcode(); + sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); + + if(GetPlayer()->GetDontMove()) + return; /* extract packet */ MovementInfo movementInfo; - uint32 MovementFlags; - - recv_data >> MovementFlags; - recv_data >> movementInfo.unk1; - recv_data >> movementInfo.time; - recv_data >> movementInfo.x; - recv_data >> movementInfo.y; - recv_data >> movementInfo.z; - recv_data >> movementInfo.o; - - if(MovementFlags & MOVEMENTFLAG_ONTRANSPORT) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4); - - recv_data >> movementInfo.t_guid; - recv_data >> movementInfo.t_x; - recv_data >> movementInfo.t_y; - recv_data >> movementInfo.t_z; - recv_data >> movementInfo.t_o; - recv_data >> movementInfo.t_time; - } - - if(MovementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - - recv_data >> movementInfo.s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up - } - - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - - recv_data >> movementInfo.fallTime; // duration of last jump (when in jump duration from jump begin to now) - - if(MovementFlags & MOVEMENTFLAG_JUMPING) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4); - - recv_data >> movementInfo.j_unk; // constant, but different when jumping in water and on land? - recv_data >> movementInfo.j_sinAngle; // sin of angle between orientation0 and players orientation - recv_data >> movementInfo.j_cosAngle; // cos of angle between orientation0 and players orientation - recv_data >> movementInfo.j_xyspeed; // speed of xy movement - } - - if(MovementFlags & MOVEMENTFLAG_SPLINE) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - - recv_data >> movementInfo.u_unk1; // unknown - } + ReadMovementInfo(recv_data, &movementInfo); /*----------------*/ if(recv_data.size() != recv_data.rpos()) @@ -248,22 +192,8 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) if (!Trinity::IsValidMapCoord(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o)) return; - // Handle possessed unit movement separately - Unit* pos_unit = GetPlayer()->GetCharm(); - if (pos_unit && pos_unit->isPossessed()) // can be charmed but not possessed - { - HandlePossessedMovement(recv_data, movementInfo, MovementFlags); - return; - } - - if (GetPlayer()->GetDontMove()) - return; - - //Save movement flags - GetPlayer()->SetUnitMovementFlags(MovementFlags); - /* handle special cases */ - if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT) + if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) { // transports size limited // (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped) @@ -282,9 +212,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { if ((*iter)->GetGUID() == movementInfo.t_guid) { - // unmount before boarding - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); - GetPlayer()->m_transport = (*iter); (*iter)->AddPassenger(GetPlayer()); break; @@ -301,13 +228,14 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) movementInfo.t_z = 0.0f; movementInfo.t_o = 0.0f; movementInfo.t_time = 0; + movementInfo.t_seat = -1; } // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). - if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight()) + if (opcode == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight()) GetPlayer()->HandleFallDamage(movementInfo); - if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater()) + if(((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater()) { // now client not include swimming flag in case jumping under water GetPlayer()->SetInWater( !GetPlayer()->IsInWater() || GetPlayer()->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) ); @@ -316,100 +244,54 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) /*----------------------*/ /* process position-change */ - recv_data.put<uint32>(5, getMSTime()); // offset flags(4) + unk(1) - WorldPacket data(recv_data.GetOpcode(), (GetPlayer()->GetPackGUID().size()+recv_data.size())); - data.append(GetPlayer()->GetPackGUID()); + Unit *mover = _player->m_mover; + recv_data.put<uint32>(6, getMSTime()); // fix time, offset flags(4) + unk(2) + WorldPacket data(recv_data.GetOpcode(), (mover->GetPackGUID().size()+recv_data.size())); + data.append(_player->m_mover->GetPackGUID()); // use mover guid data.append(recv_data.contents(), recv_data.size()); GetPlayer()->SendMessageToSet(&data, false); - GetPlayer()->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); - GetPlayer()->m_movementInfo = movementInfo; - if (GetPlayer()->m_lastFallTime >= movementInfo.fallTime || GetPlayer()->m_lastFallZ <=movementInfo.z || recv_data.GetOpcode() == MSG_MOVE_FALL_LAND) - GetPlayer()->SetFallInformation(movementInfo.fallTime, movementInfo.z); - - if(GetPlayer()->isMovingOrTurning()) - GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - - if(movementInfo.z < -500.0f) - GetPlayer()->HandleFallUnderMap(); -} - -void WorldSession::HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& movementInfo, uint32& MovementFlags) -{ - // Whatever the client is controlling, it will send the GUID of the original player. - // If current player is controlling, it must be handled like the controlled player sent these opcodes - - Unit* pos_unit = GetPlayer()->GetCharm(); - - if (pos_unit->GetTypeId() == TYPEID_PLAYER && ((Player*)pos_unit)->GetDontMove()) - return; - - //Save movement flags - pos_unit->SetUnitMovementFlags(MovementFlags); - - // Remove possession if possessed unit enters a transport - if (MovementFlags & MOVEMENTFLAG_ONTRANSPORT) + if(!_player->GetCharmGUID()) // nothing is charmed { - GetPlayer()->RemovePossess(true); - return; + _player->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + _player->m_movementInfo = movementInfo; + _player->SetUnitMovementFlags(movementInfo.flags); } - - recv_data.put<uint32>(5, getMSTime()); - WorldPacket data(recv_data.GetOpcode(), pos_unit->GetPackGUID().size()+recv_data.size()); - data.append(pos_unit->GetPackGUID()); - data.append(recv_data.contents(), recv_data.size()); - // Send the packet to self but not to the possessed player; for creatures the first bool is irrelevant - pos_unit->SendMessageToSet(&data, true, false); - - // Possessed is a player - if (pos_unit->GetTypeId() == TYPEID_PLAYER) + else { - Player* plr = (Player*)pos_unit; - - if (recv_data.GetOpcode() == MSG_MOVE_FALL_LAND) - plr->HandleFallDamage(movementInfo); - - if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != plr->IsInWater()) + if(mover->GetTypeId() != TYPEID_PLAYER) // unit, creature, pet, vehicle... { - // Now client not include swimming flag in case jumping under water - plr->SetInWater( !plr->IsInWater() || plr->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) ); + if(Map *map = mover->GetMap()) + map->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + mover->SetUnitMovementFlags(movementInfo.flags); } - - plr->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o, false); - plr->m_movementInfo = movementInfo; - - if(plr->isMovingOrTurning()) - plr->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); - - if(movementInfo.z < -500.0f) + else // player { - GetPlayer()->RemovePossess(false); - plr->HandleFallUnderMap(); + ((Player*)mover)->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + ((Player*)mover)->m_movementInfo = movementInfo; + ((Player*)mover)->SetUnitMovementFlags(movementInfo.flags); } } - else // Possessed unit is a creature - { - Map* map = MapManager::Instance().GetMap(pos_unit->GetMapId(), pos_unit); - map->CreatureRelocation((Creature*)pos_unit, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); - } + + if (GetPlayer()->m_lastFallTime >= movementInfo.fallTime || GetPlayer()->m_lastFallZ <=movementInfo.z || recv_data.GetOpcode() == MSG_MOVE_FALL_LAND) + GetPlayer()->SetFallInformation(movementInfo.fallTime, movementInfo.z); + + if(GetPlayer()->isMovingOrTurning()) + GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + + if(movementInfo.z < -500.0f) + GetPlayer()->HandleFallUnderMap(); } void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) { - CHECK_PACKET_SIZE(recv_data, 8+4+4+1+4+4+4+4+4); + sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode()); + + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4); /* extract packet */ uint64 guid; - uint8 unkB; - uint32 unk1, flags, time, fallTime; - float x, y, z, orientation; - - uint64 t_GUID; - float t_x, t_y, t_z, t_o; - uint32 t_time; - float s_pitch; - float j_unk1, j_sinAngle, j_cosAngle, j_xyspeed; - float u_unk1; + uint32 unk1; float newspeed; recv_data >> guid; @@ -420,47 +302,10 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) // continue parse packet - recv_data >> unk1; - recv_data >> flags >> unkB >> time; - recv_data >> x >> y >> z >> orientation; - if (flags & MOVEMENTFLAG_ONTRANSPORT) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4+4+4+4+4); - - recv_data >> t_GUID; - recv_data >> t_x >> t_y >> t_z >> t_o >> t_time; - } - if (flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - - recv_data >> s_pitch; // pitch, -1.55=looking down, 0=looking straight forward, +1.55=looking up - } - - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); - - recv_data >> fallTime; // duration of last jump (when in jump duration from jump begin to now) - - if ((flags & MOVEMENTFLAG_JUMPING) || (flags & MOVEMENTFLAG_FALLING)) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4+4+4+4); - - recv_data >> j_unk1; // ?constant, but different when jumping in water and on land? - recv_data >> j_sinAngle >> j_cosAngle; // sin + cos of angle between orientation0 and players orientation - recv_data >> j_xyspeed; // speed of xy movement - } - - if(flags & MOVEMENTFLAG_SPLINE) - { - // recheck - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); + recv_data >> unk1; // counter or moveEvent - recv_data >> u_unk1; // unknown - } + MovementInfo movementInfo; + ReadMovementInfo(recv_data, &movementInfo); // recheck CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); @@ -473,7 +318,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) UnitMoveType move_type; UnitMoveType force_move_type; - static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack" }; + static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "RunBack", "Swim", "SwimBack", "TurnRate", "Flight", "FlightBack", "PitchRate" }; uint16 opcode = recv_data.GetOpcode(); switch(opcode) @@ -486,6 +331,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break; case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break; case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break; + case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break; default: sLog.outError("WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: %u", opcode); return; @@ -520,20 +366,61 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data) { sLog.outDebug("WORLD: Recvd CMSG_SET_ACTIVE_MOVER"); + recv_data.hexlike(); - CHECK_PACKET_SIZE(recv_data,8); + CHECK_PACKET_SIZE(recv_data, 8); uint64 guid; recv_data >> guid; - WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement - data << uint32(0x00000000); // on blizz it increments periodically - SendPacket(&data); + if(_player->m_mover->GetGUID() != guid) + { + sLog.outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is " I64FMT " and should be " I64FMT, _player->m_mover->GetGUID(), guid); + return; + } } -void WorldSession::HandleNotActiveMoverOpcode(WorldPacket& /*recv_data*/) +void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data) { sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER"); + recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8); + + uint64 old_mover_guid; + recv_data >> old_mover_guid; + + if(_player->m_mover->GetGUID() == old_mover_guid) + { + sLog.outError("HandleMoveNotActiveMover: incorrect mover guid: mover is " I64FMT " and should be " I64FMT " instead of " I64FMT, _player->m_mover->GetGUID(), _player->GetGUID(), old_mover_guid); + return; + } + + MovementInfo mi; + ReadMovementInfo(recv_data, &mi); + _player->m_movementInfo = mi; +} + +void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_DISMISS_CONTROLLED_VEHICLE"); + recv_data.hexlike(); + + uint64 vehicleGUID = _player->GetCharmGUID(); + + if(!vehicleGUID) // something wrong here... + return; + + MovementInfo mi; + ReadMovementInfo(recv_data, &mi); + _player->m_movementInfo = mi; + + // using charm guid, because we don't have vehicle guid... + if(Vehicle *vehicle = ObjectAccessor::GetVehicle(vehicleGUID)) + { + _player->ExitVehicle(vehicle); + vehicle->Dismiss(); + } } void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/) diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index fd23991392a..1865f90ea27 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -166,25 +166,25 @@ void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) { TrainerSpell const* tSpell = *itr; - if(!_player->IsSpellFitByClassAndRace(tSpell->spell)) + if(!_player->IsSpellFitByClassAndRace(tSpell->learnedSpell)) continue; ++count; - bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->spell); + bool primary_prof_first_rank = spellmgr.IsPrimaryProfessionFirstRankSpell(tSpell->learnedSpell); - SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->spell); + SpellChainNode const* chain_node = spellmgr.GetSpellChainNode(tSpell->learnedSpell); uint32 req_spell = spellmgr.GetSpellRequired(tSpell->spell); - data << uint32(tSpell->spell); + data << uint32(tSpell->spell); // learned spell (or cast-spell in profession case) data << uint8(_player->GetTrainerSpellState(tSpell)); - data << uint32(floor(tSpell->spellcost * fDiscountMod)); + data << uint32(floor(tSpell->spellCost * fDiscountMod)); data << uint32(primary_prof_first_rank ? 1 : 0); // primary prof. learn confirmation dialog data << uint32(primary_prof_first_rank ? 1 : 0); // must be equal prev. field to have learn button in enabled state - data << uint8(tSpell->reqlevel); - data << uint32(tSpell->reqskill); - data << uint32(tSpell->reqskillvalue); + data << uint8(tSpell->reqLevel); + data << uint32(tSpell->reqSkill); + data << uint32(tSpell->reqSkillValue); data << uint32(chain_node && chain_node->prev ? chain_node->prev : req_spell); data << uint32(chain_node && chain_node->prev ? req_spell : 0); data << uint32(0); @@ -235,12 +235,14 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) return; // apply reputation discount - uint32 nSpellCost = uint32(floor(trainer_spell->spellcost * _player->GetReputationPriceDiscount(unit))); + uint32 nSpellCost = uint32(floor(trainer_spell->spellCost * _player->GetReputationPriceDiscount(unit))); // check money requirement if(_player->GetMoney() < nSpellCost ) return; + _player->ModifyMoney( -int32(nSpellCost) ); + WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); // visual effect on trainer data << uint64(guid) << uint32(0xB3); SendPacket(&data); @@ -249,13 +251,15 @@ void WorldSession::HandleTrainerBuySpellOpcode( WorldPacket & recv_data ) data << uint64(_player->GetGUID()) << uint32(0x016A); SendPacket(&data); - _player->ModifyMoney( -int32(nSpellCost) ); - - // learn explicitly to prevent lost money at lags, learning spell will be only show spell animation - _player->learnSpell(trainer_spell->spell); + // learn explicitly or cast explicitly + if(trainer_spell->IsCastable ()) + //FIXME: prof. spell entry in trainer list not marked gray until list re-open. + _player->CastSpell(_player,trainer_spell->spell,true); + else + _player->learnSpell(spellId,false); data.Initialize(SMSG_TRAINER_BUY_SUCCEEDED, 12); - data << uint64(guid) << uint32(spellId); + data << uint64(guid) << uint32(trainer_spell->spell); SendPacket(&data); } @@ -528,13 +532,12 @@ void WorldSession::SendStablePet(uint64 guid ) data << uint32(pet->GetEntry()); data << uint32(pet->getLevel()); data << pet->GetName(); // petname - data << uint32(pet->GetLoyaltyLevel()); // loyalty - data << uint8(0x01); // client slot 1 == current pet (0) + data << uint8(0x01); // flags?, client slot 1 == current pet (0) ++num; } - // 0 1 2 3 4 5 6 - QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, loyalty, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow()); + // 0 1 2 3 4 5 + QueryResult* result = CharacterDatabase.PQuery("SELECT owner, slot, id, entry, level, name FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow()); if(result) { @@ -545,8 +548,7 @@ void WorldSession::SendStablePet(uint64 guid ) data << uint32(fields[2].GetUInt32()); // petnumber data << uint32(fields[3].GetUInt32()); // creature entry data << uint32(fields[4].GetUInt32()); // level - data << fields[6].GetString(); // name - data << uint32(fields[5].GetUInt32()); // loyalty + data << fields[5].GetString(); // name data << uint8(fields[1].GetUInt32()+1); // slot ++num; @@ -596,7 +598,7 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data ) uint32 free_slot = 1; - QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 3 ORDER BY slot ",_player->GetGUIDLow()); + QueryResult *result = CharacterDatabase.PQuery("SELECT owner,slot,id FROM character_pet WHERE owner = '%u' AND slot > 0 AND slot < 5 ORDER BY slot ",_player->GetGUIDLow()); if(result) { do @@ -660,7 +662,7 @@ void WorldSession::HandleUnstablePet( WorldPacket & recv_data ) Pet *newpet = NULL; - QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 3",_player->GetGUIDLow(),petnumber); + QueryResult *result = CharacterDatabase.PQuery("SELECT entry FROM character_pet WHERE owner = '%u' AND id = '%u' AND slot > 0 AND slot < 5",_player->GetGUIDLow(),petnumber); if(result) { Field *fields = result->Fetch(); @@ -704,7 +706,7 @@ void WorldSession::HandleBuyStableSlot( WorldPacket & recv_data ) WorldPacket data(SMSG_STABLE_RESULT, 200); - if(GetPlayer()->m_stableSlots < 2) // max slots amount = 2 + if(GetPlayer()->m_stableSlots < 4) // max slots amount = 4 { StableSlotPricesEntry const *SlotPrice = sStableSlotPricesStore.LookupEntry(GetPlayer()->m_stableSlots+1); if(_player->GetMoney() >= SlotPrice->Price) diff --git a/src/game/NPCHandler.h b/src/game/NPCHandler.h index 096017b1054..e6e97df696b 100644 --- a/src/game/NPCHandler.h +++ b/src/game/NPCHandler.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/NullCreatureAI.cpp b/src/game/NullCreatureAI.cpp index 164aa2f7974..37dcdc3bc9d 100644 --- a/src/game/NullCreatureAI.cpp +++ b/src/game/NullCreatureAI.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/NullCreatureAI.h b/src/game/NullCreatureAI.h index a9814c9c5e0..7d88518ab1a 100644 --- a/src/game/NullCreatureAI.h +++ b/src/game/NullCreatureAI.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 1d5db0e925e..14a893f243e 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,8 +58,9 @@ uint32 GuidHigh2TypeId(uint32 guid_hi) case HIGHGUID_DYNAMICOBJECT:return TYPEID_DYNAMICOBJECT; case HIGHGUID_CORPSE: return TYPEID_CORPSE; case HIGHGUID_MO_TRANSPORT: return TYPEID_GAMEOBJECT; + case HIGHGUID_VEHICLE: return TYPEID_UNIT; } - return 10; // unknown + return MAX_TYPEID; // unknown } Object::Object( ) @@ -146,15 +147,9 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c /** lower flag1 **/ if(target == this) // building packet for oneself - { flags |= UPDATEFLAG_SELF; - /*** temporary reverted - until real source of stack corruption will not found - updatetype = UPDATETYPE_CREATE_OBJECT2; - ****/ - } - - if(flags & UPDATEFLAG_HASPOSITION) + if(flags & UPDATEFLAG_HAS_POSITION) { // UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses... if(isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER)) @@ -180,6 +175,12 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c break; } } + + if(isType(TYPEMASK_UNIT)) + { + if(((Unit*)this)->getVictim()) + flags |= UPDATEFLAG_HAS_TARGET; + } } //sLog.outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updatetype, m_objectTypeId, flags, flags2); @@ -251,11 +252,18 @@ void Object::DestroyForPlayer(Player *target) const WorldPacket data(SMSG_DESTROY_OBJECT, 8); data << GetGUID(); + data << uint8(0); // WotLK (bool) target->GetSession()->SendPacket( &data ); } -void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 ) const +void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2) const { + uint16 unk_flags = ((GetTypeId() == TYPEID_PLAYER) ? ((Player*)this)->m_movementInfo.unk1 : 0); + + if(GetTypeId() == TYPEID_UNIT) + if(((Creature*)this)->isVehicle()) + unk_flags |= 0x20; // always allow pitch + *data << (uint8)flags; // update flags // 0x20 @@ -292,12 +300,12 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 } *data << uint32(flags2); // movement flags - *data << uint8(0); // unk 2.3.0 + *data << uint16(unk_flags); // unknown 2.3.0 *data << uint32(getMSTime()); // time (in milliseconds) } // 0x40 - if (flags & UPDATEFLAG_HASPOSITION) + if (flags & UPDATEFLAG_HAS_POSITION) { // 0x02 if(flags & UPDATEFLAG_TRANSPORT && ((GameObject*)this)->GetGoType() == GAMEOBJECT_TYPE_MO_TRANSPORT) @@ -330,12 +338,13 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 *data << (float)((Player*)this)->GetTransOffsetZ(); *data << (float)((Player*)this)->GetTransOffsetO(); *data << (uint32)((Player*)this)->GetTransTime(); + *data << (int8)((Player*)this)->GetTransSeat(); } //TrinIty currently not have support for other than player on transport } // 0x02200000 - if(flags2 & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) + if((flags2 & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) || (unk_flags & 0x20)) { if(GetTypeId() == TYPEID_PLAYER) *data << (float)((Player*)this)->m_movementInfo.s_pitch; @@ -384,6 +393,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 *data << ((Unit*)this)->GetSpeed( MOVE_FLIGHT ); *data << ((Unit*)this)->GetSpeed( MOVE_FLIGHT_BACK ); *data << ((Unit*)this)->GetSpeed( MOVE_TURN_RATE ); + *data << ((Unit*)this)->GetSpeed( MOVE_PITCH_RATE ); // 0x08000000 if(flags2 & MOVEMENTFLAG_SPLINE2) @@ -448,6 +458,8 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 *data << path.GetNodes()[i].z; } + *data << uint8(0); // added in 3.0.8 + /*for(uint32 i = 0; i < poscount; i++) { // path points @@ -485,7 +497,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 break; case TYPEID_PLAYER: if(flags & UPDATEFLAG_SELF) - *data << uint32(0x00000015); // unk, can be 0x15 or 0x22 + *data << uint32(0x0000002F); // unk, can be 0x15 or 0x22 else *data << uint32(0x00000008); // unk, can be 0x7 or 0x8 break; @@ -508,6 +520,15 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 case TYPEID_CORPSE: *data << uint32(GetGUIDHigh()); // GetGUIDHigh() break; + case TYPEID_UNIT: + *data << uint32(0x0000000B); // unk, can be 0xB or 0xC + break; + case TYPEID_PLAYER: + if(flags & UPDATEFLAG_SELF) + *data << uint32(0x0000002F); // unk, can be 0x15 or 0x22 + else + *data << uint32(0x00000008); // unk, can be 0x7 or 0x8 + break; default: *data << uint32(0x00000000); // unk break; @@ -515,9 +536,12 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 } // 0x4 - if(flags & UPDATEFLAG_FULLGUID) + if(flags & UPDATEFLAG_HAS_TARGET) // packed guid (current target guid) { - *data << uint8(0); // packed guid (probably target guid) + if(Unit *victim = ((Unit*)this)->getVictim()) + data->append(victim->GetPackGUID()); + else + *data << uint8(0); } // 0x2 @@ -525,6 +549,13 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 { *data << uint32(getMSTime()); // ms time } + + // 0x80 + if(flags & UPDATEFLAG_VEHICLE) // unused for now + { + *data << uint32(((Vehicle*)this)->GetVehicleId()); // vehicle id + *data << float(0); // facing adjustment + } } void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *updateMask, Player *target) const @@ -540,10 +571,10 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask if ( ((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster()) { IsActivateToQuest = true; - updateMask->SetBit(GAMEOBJECT_DYN_FLAGS); + updateMask->SetBit(GAMEOBJECT_DYNAMIC); } - if (GetUInt32Value(GAMEOBJECT_ARTKIT)) - updateMask->SetBit(GAMEOBJECT_ARTKIT); + if (((GameObject*)this)->GetGoArtKit()) + updateMask->SetBit(GAMEOBJECT_BYTES_1); } } else //case UPDATETYPE_VALUES @@ -554,8 +585,8 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask { IsActivateToQuest = true; } - updateMask->SetBit(GAMEOBJECT_DYN_FLAGS); - updateMask->SetBit(GAMEOBJECT_ANIMPROGRESS); + updateMask->SetBit(GAMEOBJECT_DYNAMIC); + updateMask->SetBit(GAMEOBJECT_BYTES_1); } } @@ -572,7 +603,6 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask if( updateMask->GetBit( index ) ) { // remove custom flag before send - if( index == UNIT_NPC_FLAGS ) *data << uint32(m_uint32Values[ index ] & ~(UNIT_NPC_FLAG_GUARD + UNIT_NPC_FLAG_OUTDOORPVP)); // FIXME: Some values at server stored in float format but must be sent to client in uint32 format @@ -673,7 +703,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask if( updateMask->GetBit( index ) ) { // send in current format (float as float, uint32 as uint32) - if ( index == GAMEOBJECT_DYN_FLAGS ) + if ( index == GAMEOBJECT_DYNAMIC ) { if(IsActivateToQuest ) { @@ -1054,6 +1084,9 @@ 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), + mSemaphoreTeleport(false) { m_positionX = 0.0f; m_positionY = 0.0f; @@ -1106,26 +1139,27 @@ void WorldObject::RemoveFromWorld() Object::RemoveFromWorld(); } -void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid ) +void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid, uint32 phaseMask ) { Object::_Create(guidlow, 0, guidhigh); m_mapId = mapid; + m_phaseMask = phaseMask; } uint32 WorldObject::GetZoneId() const { - return MapManager::Instance().GetBaseMap(m_mapId)->GetZoneId(m_positionX,m_positionY); + return MapManager::Instance().GetBaseMap(m_mapId)->GetZoneId(m_positionX,m_positionY,m_positionZ); } uint32 WorldObject::GetAreaId() const { - return MapManager::Instance().GetBaseMap(m_mapId)->GetAreaId(m_positionX,m_positionY); + return MapManager::Instance().GetBaseMap(m_mapId)->GetAreaId(m_positionX,m_positionY,m_positionZ); } InstanceData* WorldObject::GetInstanceData() { - Map *map = MapManager::Instance().GetMap(m_mapId, this); + Map *map = GetMap(); return map->IsDungeon() ? ((InstanceMap*)map)->GetInstanceData() : NULL; } @@ -1417,9 +1451,9 @@ void WorldObject::MonsterSay(int32 textId, uint32 language, uint64 TargetGuid) cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - Trinity::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_SAY, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY)); - Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo> say_worker(say_do); - TypeContainerVisitor<Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker); + MaNGOS::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_SAY, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY)); + MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo> say_worker(this,say_do); + TypeContainerVisitor<MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker); CellLock<GridReadGuard> cell_lock(cell, p); cell_lock->Visit(cell_lock, message, *GetMap()); } @@ -1432,9 +1466,9 @@ void WorldObject::MonsterYell(int32 textId, uint32 language, uint64 TargetGuid) cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - Trinity::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL)); - Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo> say_worker(say_do); - TypeContainerVisitor<Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker); + MaNGOS::MessageChatLocaleCacheDo say_do(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL)); + MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo> say_worker(this,say_do); + TypeContainerVisitor<MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker); CellLock<GridReadGuard> cell_lock(cell, p); cell_lock->Visit(cell_lock, message, *GetMap()); } @@ -1447,9 +1481,9 @@ void WorldObject::MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossE cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - Trinity::MessageChatLocaleCacheDo say_do(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId,LANG_UNIVERSAL,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); - Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo> say_worker(say_do); - TypeContainerVisitor<Trinity::PlayerWorker<Trinity::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker); + MaNGOS::MessageChatLocaleCacheDo say_do(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId,LANG_UNIVERSAL,TargetGuid,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE)); + MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo> say_worker(this,say_do); + TypeContainerVisitor<MaNGOS::PlayerWorker<MaNGOS::MessageChatLocaleCacheDo>, WorldTypeMapContainer > message(say_worker); CellLock<GridReadGuard> cell_lock(cell, p); cell_lock->Visit(cell_lock, message, *GetMap()); } @@ -1501,7 +1535,7 @@ void WorldObject::BuildHeartBeatMsg(WorldPacket *data) const data->Initialize(MSG_MOVE_HEARTBEAT, 32); data->append(GetPackGUID()); *data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags - *data << uint8(0); // 2.3.0 + *data << uint16(0); // 2.3.0 *data << getMSTime(); // time *data << m_positionX; *data << m_positionY; @@ -1520,7 +1554,7 @@ void WorldObject::BuildTeleportAckMsg(WorldPacket *data, float x, float y, float data->append(GetPackGUID()); *data << uint32(0); // this value increments every time *data << uint32(((Unit*)this)->GetUnitMovementFlags()); // movement flags - *data << uint8(0); // 2.3.0 + *data << uint16(0); // 2.3.0 *data << getMSTime(); // time *data << x; *data << y; @@ -1577,7 +1611,7 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa if (GetTypeId()==TYPEID_PLAYER) team = ((Player*)this)->GetTeam(); - if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), GetMap(), id, team)) + if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), GetMap(), GetPhaseMask(), id, team)) { delete pCreature; return NULL; @@ -1616,17 +1650,16 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float { if(!IsInWorld()) return NULL; - Map * map = GetMap(); - if(!map) - return NULL; + GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry); if(!goinfo) { sLog.outErrorDb("Gameobject template %u not found in database!", entry); return NULL; } + Map *map = GetMap(); GameObject *go = new GameObject(); - if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),entry,map,x,y,z,ang,rotation0,rotation1,rotation2,rotation3,100,1)) + if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), entry, map, GetPhaseMask(), x,y,z,ang,rotation0,rotation1,rotation2,rotation3,100,1)) return NULL; go->SetRespawnTime(respawnTime); if(GetTypeId()==TYPEID_PLAYER || GetTypeId()==TYPEID_UNIT) //not sure how to handle this @@ -1685,4 +1718,10 @@ void WorldObject::GetGroundPoint(float &x, float &y, float &z, float dist, float UpdateGroundPositionZ(x, y, z); } +void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update) +{ + m_phaseMask = newPhaseMask; + if(update && IsInWorld()) + ObjectAccessor::UpdateObjectVisibility(this); +} diff --git a/src/game/Object.h b/src/game/Object.h index d4d9759ed1b..8bb8d770519 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -56,7 +56,8 @@ enum TypeMask TYPEMASK_DYNAMICOBJECT = 0x0040, TYPEMASK_CORPSE = 0x0080, TYPEMASK_AIGROUP = 0x0100, - TYPEMASK_AREATRIGGER = 0x0200 + TYPEMASK_AREATRIGGER = 0x0200, + TYPEMASK_FARSIGHTOBJ = TYPEMASK_PLAYER | TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT }; enum TypeID @@ -72,6 +73,7 @@ enum TypeID TYPEID_AIGROUP = 8, TYPEID_AREATRIGGER = 9 }; +#define MAX_TYPEID 10 uint32 GuidHigh2TypeId(uint32 guid_hi); @@ -87,6 +89,12 @@ enum TempSummonType TEMPSUMMON_MANUAL_DESPAWN = 8 // despawns when UnSummon() is called }; +enum PhaseMasks +{ + PHASEMASK_NORMAL = 0x00000001, + PHASEMASK_ANYWHERE = 0xFFFFFFFF +}; + class WorldPacket; class UpdateData; class ByteBuffer; @@ -358,7 +366,7 @@ class TRINITY_DLL_SPEC WorldObject : public Object virtual void Update ( uint32 /*time_diff*/ ) { } - void _Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid ); + void _Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid, uint32 phaseMask); void Relocate(float x, float y, float z, float orientation) { @@ -420,9 +428,13 @@ class TRINITY_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; } + virtual void SetPhaseMask(uint32 newPhaseMask, bool update); + uint32 GetPhaseMask() const { return m_phaseMask; } + bool InSamePhase(WorldObject const* obj) const { return InSamePhase(obj->GetPhaseMask()); } + bool InSamePhase(uint32 phasemask) const { return GetPhaseMask()==0 && phasemask==0 || (GetPhaseMask() & phasemask); } + uint32 GetZoneId() const; uint32 GetAreaId() const; @@ -439,7 +451,11 @@ class TRINITY_DLL_SPEC WorldObject : public Object float GetDistance2d(const WorldObject* obj) const; float GetDistance2d(const float x, const float y) const; float GetDistanceZ(const WorldObject* obj) const; - bool IsInMap(const WorldObject* obj) const { return GetMapId()==obj->GetMapId() && GetInstanceId()==obj->GetInstanceId(); } + bool IsInMap(const WorldObject* obj) const + { + return IsInWorld() && obj->IsInWorld() && GetMapId()==obj->GetMapId() && + GetInstanceId()==obj->GetInstanceId() && InSamePhase(obj); + } bool IsWithinDistInMap(const WorldObject* obj, const float dist2compare, const bool is3D = true) const; bool IsWithinLOS(const float x, const float y, const float z ) const; bool IsWithinLOSInMap(const WorldObject* obj) const; @@ -499,7 +515,9 @@ class TRINITY_DLL_SPEC WorldObject : public Object bool m_isActive; private: - uint32 m_mapId; + 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 float m_positionX; float m_positionY; @@ -507,7 +525,5 @@ class TRINITY_DLL_SPEC WorldObject : public Object float m_orientation; bool mSemaphoreTeleport; - - uint32 m_InstanceId; }; #endif diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index d2b0878c595..95ead040cb8 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,6 +38,7 @@ #include "Opcodes.h" #include "ObjectDefines.h" #include "MapInstanced.h" +#include "World.h" #include <cmath> @@ -45,38 +46,6 @@ INSTANTIATE_SINGLETON_2(ObjectAccessor, CLASS_LOCK); INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ZThread::FastMutex); -namespace Trinity -{ - struct TRINITY_DLL_DECL BuildUpdateForPlayer - { - Player &i_player; - UpdateDataMapType &i_updatePlayers; - - BuildUpdateForPlayer(Player &player, UpdateDataMapType &data_map) : i_player(player), i_updatePlayers(data_map) {} - - void Visit(PlayerMapType &m) - { - for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) - { - if( iter->getSource() == &i_player ) - continue; - - UpdateDataMapType::iterator iter2 = i_updatePlayers.find(iter->getSource()); - if( iter2 == i_updatePlayers.end() ) - { - std::pair<UpdateDataMapType::iterator, bool> p = i_updatePlayers.insert( ObjectAccessor::UpdateDataValueType(iter->getSource(), UpdateData()) ); - assert(p.second); - iter2 = p.first; - } - - i_player.BuildValuesUpdateBlockForPlayer(&iter2->second, iter2->first); - } - } - - template<class SKIP> void Visit(GridRefManager<SKIP> &) {} - }; -} - ObjectAccessor::ObjectAccessor() {} ObjectAccessor::~ObjectAccessor() {} @@ -129,11 +98,14 @@ ObjectAccessor::GetNPCIfCanInteractWith(Player const &player, uint64 guid, uint3 } Creature* -ObjectAccessor::GetCreatureOrPet(WorldObject const &u, uint64 guid) +ObjectAccessor::GetCreatureOrPetOrVehicle(WorldObject const &u, uint64 guid) { if(Creature *unit = GetPet(guid)) return unit; + if(Creature *unit = GetVehicle(guid)) + return unit; + return GetCreature(u, guid); } @@ -162,18 +134,23 @@ ObjectAccessor::GetUnit(WorldObject const &u, uint64 guid) if(IS_PLAYER_GUID(guid)) return FindPlayer(guid); - return GetCreatureOrPet(u, guid); + return GetCreatureOrPetOrVehicle(u, guid); } Corpse* ObjectAccessor::GetCorpse(WorldObject const &u, uint64 guid) { Corpse * ret = GetObjectInWorld(guid, (Corpse*)NULL); - if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL; + if(!ret) + return NULL; + if(ret->GetMapId() != u.GetMapId()) + return NULL; + if(ret->GetInstanceId() != u.GetInstanceId()) + return NULL; return ret; } -Object* ObjectAccessor::GetObjectByTypeMask(Player const &p, uint64 guid, uint32 typemask) +Object* ObjectAccessor::GetObjectByTypeMask(WorldObject const &p, uint64 guid, uint32 typemask) { Object *obj = NULL; @@ -185,7 +162,7 @@ Object* ObjectAccessor::GetObjectByTypeMask(Player const &p, uint64 guid, uint32 if(typemask & TYPEMASK_UNIT) { - obj = GetCreatureOrPet(p,guid); + obj = GetCreatureOrPetOrVehicle(p,guid); if(obj) return obj; } @@ -201,9 +178,9 @@ Object* ObjectAccessor::GetObjectByTypeMask(Player const &p, uint64 guid, uint32 if(obj) return obj; } - if(typemask & TYPEMASK_ITEM) + if(typemask & TYPEMASK_ITEM && p.GetTypeId() == TYPEID_PLAYER) { - obj = p.GetItemByGuid( guid ); + obj = ((Player const &)p).GetItemByGuid( guid ); if(obj) return obj; } @@ -214,15 +191,25 @@ GameObject* ObjectAccessor::GetGameObject(WorldObject const &u, uint64 guid) { GameObject * ret = GetObjectInWorld(guid, (GameObject*)NULL); - if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL; + if(!ret) + return NULL; + if(ret->GetMapId() != u.GetMapId()) + return NULL; + if(ret->GetInstanceId() != u.GetInstanceId()) + return NULL; return ret; } DynamicObject* -ObjectAccessor::GetDynamicObject(Unit const &u, uint64 guid) +ObjectAccessor::GetDynamicObject(WorldObject const &u, uint64 guid) { DynamicObject * ret = GetObjectInWorld(guid, (DynamicObject*)NULL); - if(ret && ret->GetMapId() != u.GetMapId()) ret = NULL; + if(!ret) + return NULL; + if(ret->GetMapId() != u.GetMapId()) + return NULL; + if(ret->GetInstanceId() != u.GetInstanceId()) + return NULL; return ret; } @@ -273,22 +260,6 @@ ObjectAccessor::UpdateObject(Object* obj, Player* exceptPlayer) } void -ObjectAccessor::AddUpdateObject(Object *obj) -{ - Guard guard(i_updateGuard); - i_objects.insert(obj); -} - -void -ObjectAccessor::RemoveUpdateObject(Object *obj) -{ - Guard guard(i_updateGuard); - std::set<Object *>::iterator iter = i_objects.find(obj); - if( iter != i_objects.end() ) - i_objects.erase( iter ); -} - -void ObjectAccessor::_buildUpdateObject(Object *obj, UpdateDataMapType &update_players) { bool build_for_all = true; @@ -351,6 +322,12 @@ ObjectAccessor::GetPet(uint64 guid) return GetObjectInWorld(guid, (Pet*)NULL); } +Vehicle* +ObjectAccessor::GetVehicle(uint64 guid) +{ + return GetObjectInWorld(guid, (Vehicle*)NULL); +} + Corpse* ObjectAccessor::GetCorpseForPlayerGUID(uint64 guid) { @@ -423,7 +400,7 @@ ObjectAccessor::AddCorpsesToGrid(GridPair const& gridpair,GridType& grid,Map* ma } Corpse* -ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid) +ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia) { Corpse *corpse = GetCorpseForPlayerGUID(player_guid); if(!corpse) @@ -449,7 +426,10 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid) Corpse *bones = NULL; // create the bones only if the map and the grid is loaded at the corpse's location - if(map && !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY())) + // ignore bones creating option in case insignia + if (map && (insignia || + (map->IsBattleGroundOrArena() ? sWorld.getConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld.getConfig(CONFIG_DEATH_BONES_WORLD))) && + !map->IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY())) { // Create bones, don't change Corpse bones = new Corpse; @@ -465,6 +445,7 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid) 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); bones->SetUInt64Value(CORPSE_FIELD_OWNER, 0); @@ -602,6 +583,7 @@ template <class T> ZThread::FastMutex HashMapHolder<T>::i_lock; template class HashMapHolder<Player>; template class HashMapHolder<Pet>; +template class HashMapHolder<Vehicle>; template class HashMapHolder<GameObject>; template class HashMapHolder<DynamicObject>; template class HashMapHolder<Creature>; @@ -609,6 +591,7 @@ template class HashMapHolder<Corpse>; template Player* ObjectAccessor::GetObjectInWorld<Player>(uint32 mapid, float x, float y, uint64 guid, Player* /*fake*/); template Pet* ObjectAccessor::GetObjectInWorld<Pet>(uint32 mapid, float x, float y, uint64 guid, Pet* /*fake*/); +template Vehicle* ObjectAccessor::GetObjectInWorld<Vehicle>(uint32 mapid, float x, float y, uint64 guid, Vehicle* /*fake*/); template Creature* ObjectAccessor::GetObjectInWorld<Creature>(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/); template Corpse* ObjectAccessor::GetObjectInWorld<Corpse>(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/); template GameObject* ObjectAccessor::GetObjectInWorld<GameObject>(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/); diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index 879c73288cc..723eecb1510 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,7 @@ #include "GridDefines.h" #include "Object.h" #include "Player.h" +#include "Vehicle.h" #include <set> @@ -58,9 +59,7 @@ class HashMapHolder static void Remove(T* o) { Guard guard(i_lock); - typename MapType::iterator itr = m_objectMap.find(o->GetGUID()); - if (itr != m_objectMap.end()) - m_objectMap.erase(itr); + m_objectMap.erase(o->GetGUID()); } static T* Find(uint64 guid) @@ -139,17 +138,18 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor else return NULL; } - static Object* GetObjectByTypeMask(Player const &, uint64, uint32 typemask); + static Object* GetObjectByTypeMask(WorldObject const &, uint64, uint32 typemask); static Creature* GetNPCIfCanInteractWith(Player const &player, uint64 guid, uint32 npcflagmask); static Creature* GetCreature(WorldObject const &, uint64); - static Creature* GetCreatureOrPet(WorldObject const &, uint64); + static Creature* GetCreatureOrPetOrVehicle(WorldObject const &, uint64); static Unit* GetUnit(WorldObject const &, uint64); static Pet* GetPet(Unit const &, uint64 guid) { return GetPet(guid); } static Player* GetPlayer(Unit const &, uint64 guid) { return FindPlayer(guid); } static GameObject* GetGameObject(WorldObject const &, uint64); - static DynamicObject* GetDynamicObject(Unit const &, uint64); + static DynamicObject* GetDynamicObject(WorldObject const &, uint64); static Corpse* GetCorpse(WorldObject const &u, uint64 guid); static Pet* GetPet(uint64 guid); + static Vehicle* GetVehicle(uint64 guid); static Player* FindPlayer(uint64); Player* FindPlayerByName(const char *name) ; @@ -174,16 +174,22 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor HashMapHolder<Player>::Remove(pl); Guard guard(i_updateGuard); - - std::set<Object *>::iterator iter2 = std::find(i_objects.begin(), i_objects.end(), (Object *)pl); - if( iter2 != i_objects.end() ) - i_objects.erase(iter2); + i_objects.erase((Object *)pl); } void SaveAllPlayers(); - void AddUpdateObject(Object *obj); - void RemoveUpdateObject(Object *obj); + void AddUpdateObject(Object *obj) + { + Guard guard(i_updateGuard); + i_objects.insert(obj); + } + + void RemoveUpdateObject(Object *obj) + { + Guard guard(i_updateGuard); + i_objects.erase( obj ); + } void Update(uint32 diff); void UpdatePlayers(uint32 diff); @@ -192,7 +198,7 @@ class TRINITY_DLL_DECL ObjectAccessor : public Trinity::Singleton<ObjectAccessor void RemoveCorpse(Corpse *corpse); void AddCorpse(Corpse* corpse); void AddCorpsesToGrid(GridPair const& gridpair,GridType& grid,Map* map); - Corpse* ConvertCorpseForPlayer(uint64 player_guid); + Corpse* ConvertCorpseForPlayer(uint64 player_guid, bool insignia = false); static void UpdateObject(Object* obj, Player* exceptPlayer); static void _buildUpdateObject(Object* obj, UpdateDataMapType &); diff --git a/src/game/ObjectDefines.h b/src/game/ObjectDefines.h index 88840ebd251..39082fb5e4d 100644 --- a/src/game/ObjectDefines.h +++ b/src/game/ObjectDefines.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,6 +41,7 @@ enum HighGuid HIGHGUID_TRANSPORT = 0xF120, // blizz F120 (for GAMEOBJECT_TYPE_TRANSPORT) HIGHGUID_UNIT = 0xF130, // blizz F130 HIGHGUID_PET = 0xF140, // blizz F140 + HIGHGUID_VEHICLE = 0xF150, // blizz F550 HIGHGUID_DYNAMICOBJECT = 0xF100, // blizz F100 HIGHGUID_CORPSE = 0xF101, // blizz F100 HIGHGUID_MO_TRANSPORT = 0x1FC0, // blizz 1FC0 (for GAMEOBJECT_TYPE_MO_TRANSPORT) @@ -50,6 +51,7 @@ enum HighGuid #define IS_CREATURE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_UNIT ) #define IS_PET_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PET ) +#define IS_VEHICLE_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_VEHICLE ) #define IS_CREATURE_OR_PET_GUID(Guid)( IS_CREATURE_GUID(Guid) || IS_PET_GUID(Guid) ) #define IS_PLAYER_GUID(Guid) ( GUID_HIPART(Guid) == HIGHGUID_PLAYER && Guid!=0 ) #define IS_UNIT_GUID(Guid) ( IS_CREATURE_OR_PET_GUID(Guid) || IS_PLAYER_GUID(Guid) ) @@ -87,6 +89,7 @@ inline bool IsGuidHaveEnPart(uint64 const& guid) case HIGHGUID_TRANSPORT: case HIGHGUID_UNIT: case HIGHGUID_PET: + case HIGHGUID_VEHICLE: case HIGHGUID_MO_TRANSPORT: default: return true; @@ -106,6 +109,7 @@ inline char const* GetLogNameForGuid(uint64 guid) case HIGHGUID_TRANSPORT: return "transport"; case HIGHGUID_UNIT: return "creature"; case HIGHGUID_PET: return "pet"; + case HIGHGUID_VEHICLE: return "vehicle"; case HIGHGUID_DYNAMICOBJECT:return "dynobject"; case HIGHGUID_CORPSE: return "corpse"; case HIGHGUID_MO_TRANSPORT: return "mo_transport"; diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp index 0e2b6ae329d..89df0582de0 100644 --- a/src/game/ObjectGridLoader.cpp +++ b/src/game/ObjectGridLoader.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,7 +59,7 @@ ObjectGridRespawnMover::Visit(CreatureMapType &m) Creature * c = iter->getSource(); - assert(!c->isPet() && "ObjectGridRespawnMover don't must be called for pets"); + assert((!c->isPet() || !c->isVehicle()) && "ObjectGridRespawnMover don't must be called for pets"); Cell const& cur_cell = c->GetCurrentCell(); diff --git a/src/game/ObjectGridLoader.h b/src/game/ObjectGridLoader.h index ebaaa1f5010..b75db484463 100644 --- a/src/game/ObjectGridLoader.h +++ b/src/game/ObjectGridLoader.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 8ba8320b432..97eed337799 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -46,6 +46,7 @@ #include "Util.h" #include "WaypointManager.h" #include "InstanceData.h" //for condition_instance_data +#include "BattleGround.h" INSTANTIATE_SINGLETON_1(ObjectMgr); @@ -116,6 +117,7 @@ ObjectMgr::ObjectMgr() m_hiCharGuid = 1; m_hiCreatureGuid = 1; m_hiPetGuid = 1; + m_hiVehicleGuid = 1; m_hiItemGuid = 1; m_hiGoGuid = 1; m_hiDoGuid = 1; @@ -325,14 +327,14 @@ void ObjectMgr::RemoveArenaTeam(ArenaTeam* arenaTeam) mArenaTeamMap.erase( arenaTeam->GetId() ); } -AuctionHouseObject * ObjectMgr::GetAuctionsMap( uint32 location ) +AuctionHouseObject * ObjectMgr::GetAuctionsMap( AuctionLocation location ) { switch ( location ) { - case 6: //horde + case AUCTION_HORDE: return & mHordeAuctions; break; - case 2: //alliance + case AUCTION_ALLIANCE: return & mAllianceAuctions; break; default: //neutral @@ -340,18 +342,18 @@ AuctionHouseObject * ObjectMgr::GetAuctionsMap( uint32 location ) } } -uint32 ObjectMgr::GetAuctionCut(uint32 location, uint32 highBid) +uint32 ObjectMgr::GetAuctionCut(AuctionLocation location, uint32 highBid) { - if (location == 7 && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) + if (location == AUCTION_NEUTRAL && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) return (uint32) (0.15f * highBid * sWorld.getRate(RATE_AUCTION_CUT)); else return (uint32) (0.05f * highBid * sWorld.getRate(RATE_AUCTION_CUT)); } -uint32 ObjectMgr::GetAuctionDeposit(uint32 location, uint32 time, Item *pItem) +uint32 ObjectMgr::GetAuctionDeposit(AuctionLocation location, uint32 time, Item *pItem) { float percentance; // in 0..1 - if ( location == 7 && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) + if (location == AUCTION_NEUTRAL && !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) percentance = 0.75f; else percentance = 0.15f; @@ -842,6 +844,19 @@ void ObjectMgr::LoadCreatureTemplates() if((cInfo->npcflag & UNIT_NPC_FLAG_TRAINER) && cInfo->trainer_type >= MAX_TRAINER_TYPE) sLog.outErrorDb("Creature (Entry: %u) has wrong trainer type %u",cInfo->Entry,cInfo->trainer_type); + if(cInfo->type && !sCreatureTypeStore.LookupEntry(cInfo->type)) + { + sLog.outErrorDb("Creature (Entry: %u) has invalid creature type (%u) in `type`",cInfo->Entry,cInfo->type); + const_cast<CreatureInfo*>(cInfo)->type = CREATURE_TYPE_HUMANOID; + } + + // must exist or used hidden but used in data horse case + if(cInfo->family && !sCreatureFamilyStore.LookupEntry(cInfo->family) && cInfo->family != CREATURE_FAMILY_HORSE_CUSTOM ) + { + sLog.outErrorDb("Creature (Entry: %u) has invalid creature family (%u) in `family`",cInfo->Entry,cInfo->family); + const_cast<CreatureInfo*>(cInfo)->family = 0; + } + if(cInfo->InhabitType <= 0 || cInfo->InhabitType > INHABIT_ANYWHERE) { sLog.outErrorDb("Creature (Entry: %u) has wrong value (%u) in `InhabitType`, creature will not correctly walk/swim/fly",cInfo->Entry,cInfo->InhabitType); @@ -855,6 +870,15 @@ void ObjectMgr::LoadCreatureTemplates() sLog.outErrorDb("Creature (Entry: %u) has non-existing PetSpellDataId (%u)", cInfo->Entry, cInfo->PetSpellDataId); } + for(int i = 0; i < CREATURE_MAX_SPELLS; ++i) + { + if(cInfo->spells[i] && !sSpellStore.LookupEntry(cInfo->spells[i])) + { + sLog.outErrorDb("Creature (Entry: %u) has non-existing Spell%d (%u), set to 0", cInfo->Entry, i+1,cInfo->spells[i]); + const_cast<CreatureInfo*>(cInfo)->spells[i] = 0; + } + } + if(cInfo->MovementType >= MAX_DB_MOTION_TYPE) { sLog.outErrorDb("Creature (Entry: %u) has wrong movement generator type (%u), ignore and set to IDLE.",cInfo->Entry,cInfo->MovementType); @@ -1003,8 +1027,47 @@ void ObjectMgr::LoadEquipmentTemplates() { sEquipmentStorage.Load(); + for(uint32 i=0; i< sEquipmentStorage.MaxEntry; ++i) + { + EquipmentInfo const* eqInfo = sEquipmentStorage.LookupEntry<EquipmentInfo>(i); + + if(!eqInfo) + continue; + + for(uint8 j=0; j<3; j++) + { + if(!eqInfo->equipentry[j]) + continue; + + ItemEntry const *dbcitem = sItemStore.LookupEntry(eqInfo->equipentry[j]); + + if(!dbcitem) + { + sLog.outErrorDb("Unknown item (entry=%u) in creature_equip_template.equipentry%u for entry = %u, forced to 0.", eqInfo->equipentry[j], j+1, i); + const_cast<EquipmentInfo*>(eqInfo)->equipentry[j] = 0; + continue; + } + + if(dbcitem->InventoryType != INVTYPE_WEAPON && + dbcitem->InventoryType != INVTYPE_SHIELD && + dbcitem->InventoryType != INVTYPE_RANGED && + dbcitem->InventoryType != INVTYPE_2HWEAPON && + dbcitem->InventoryType != INVTYPE_WEAPONMAINHAND && + dbcitem->InventoryType != INVTYPE_WEAPONOFFHAND && + dbcitem->InventoryType != INVTYPE_HOLDABLE && + dbcitem->InventoryType != INVTYPE_THROWN && + dbcitem->InventoryType != INVTYPE_RANGEDRIGHT) + { + sLog.outErrorDb("Item (entry=%u) in creature_equip_template.equipentry%u for entry = %u is not equipable in a hand, forced to 0.", eqInfo->equipentry[j], j+1, i); + const_cast<EquipmentInfo*>(eqInfo)->equipentry[j] = 0; + } + } + } sLog.outString( ">> Loaded %u equipment template", sEquipmentStorage.RecordCount ); sLog.outString(); + + // This DBC is currently only used for item templates and creature equipments checks. + sItemStore.Clear(); } CreatureModelInfo const* ObjectMgr::GetCreatureModelInfo(uint32 modelid) @@ -1076,8 +1139,8 @@ void ObjectMgr::LoadCreatures() QueryResult *result = WorldDatabase.Query("SELECT creature.guid, id, map, modelid," // 4 5 6 7 8 9 10 11 "equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, spawndist, currentwaypoint," - // 12 13 14 15 16 17 - "curhealth, curmana, DeathState, MovementType, spawnMask, event " + // 12 13 14 15 16 17 18 + "curhealth, curmana, DeathState, MovementType, spawnMask, phaseMask, event " "FROM creature LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid"); if(!result) @@ -1125,7 +1188,8 @@ void ObjectMgr::LoadCreatures() data.is_dead = fields[14].GetBool(); data.movementType = fields[15].GetUInt8(); data.spawnMask = fields[16].GetUInt8(); - int16 gameEvent = fields[17].GetInt16(); + data.phaseMask = fields[17].GetUInt16(); + int16 gameEvent = fields[18].GetInt16(); CreatureInfo const* cInfo = GetCreatureTemplate(data.id); if(!cInfo) @@ -1183,6 +1247,40 @@ void ObjectMgr::LoadCreatures() } } + if(data.phaseMask==0) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.",guid,data.id ); + data.phaseMask = 1; + } + else + { + int count = 0; + for(int i=0; i < sizeof(data.phaseMask)*8; ++i) + if(data.phaseMask & (1 << i)) + ++count; + + if(count > 1) + { + uint32 phaseMask = data.phaseMask & ~PHASEMASK_NORMAL; + count = 0; + for(int i=0; i < sizeof(phaseMask)*8; ++i) + if(phaseMask & (1 << i)) + ++count; + + if(count > 1) + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with more single bit set in `phaseMask` (not visible for anyone), set to 1.",guid,data.id ); + data.phaseMask = phaseMask; + } + else + { + sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with more single bit set in `phaseMask` (not visible for anyone), set to %u (possible expected).",guid,data.id,phaseMask); + data.phaseMask = 1; + } + + } + } + if (gameEvent==0) // if not this is to be managed by GameEvent System AddCreatureToGrid(guid, &data); ++count; @@ -1233,8 +1331,8 @@ void ObjectMgr::LoadGameobjects() // 0 1 2 3 4 5 6 QueryResult *result = WorldDatabase.Query("SELECT gameobject.guid, id, map, position_x, position_y, position_z, orientation," - // 7 8 9 10 11 12 13 14 15 - "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, event " + // 7 8 9 10 11 12 13 14 15 16 + "rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state, spawnMask, phaseMask, event " "FROM gameobject LEFT OUTER JOIN game_event_gameobject ON gameobject.guid = game_event_gameobject.guid"); if(!result) @@ -1274,7 +1372,8 @@ void ObjectMgr::LoadGameobjects() data.go_state = fields[13].GetUInt32(); data.ArtKit = 0; data.spawnMask = fields[14].GetUInt8(); - int16 gameEvent = fields[15].GetInt16(); + data.phaseMask = fields[15].GetUInt16(); + int16 gameEvent = fields[16].GetInt16(); GameObjectInfo const* gInfo = GetGameObjectInfo(data.id); if(!gInfo) @@ -1283,6 +1382,12 @@ void ObjectMgr::LoadGameobjects() continue; } + if(data.phaseMask==0) + { + sLog.outErrorDb("Table `gameobject` have gameobject (GUID: %u Entry: %u) with `phaseMask`=0 (not visible for anyone), set to 1.",guid,data.id ); + data.phaseMask = 1; + } + if (gameEvent==0) // if not this is to be managed by GameEvent System AddGameobjectToGrid(guid, &data); ++count; @@ -1502,18 +1607,36 @@ void ObjectMgr::LoadAuctions() { QueryResult *result = CharacterDatabase.Query("SELECT COUNT(*) FROM auctionhouse"); if( !result ) + { + barGoLink bar(1); + bar.step(); + sLog.outString(""); + sLog.outString(">> Loaded 0 auctions. DB table `auctionhouse` is empty."); return; + } Field *fields = result->Fetch(); uint32 AuctionCount=fields[0].GetUInt32(); delete result; if(!AuctionCount) + { + barGoLink bar(1); + bar.step(); + sLog.outString(""); + sLog.outString(">> Loaded 0 auctions. DB table `auctionhouse` is empty."); return; + } result = CharacterDatabase.Query( "SELECT id,auctioneerguid,itemguid,item_template,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit,location FROM auctionhouse" ); if( !result ) + { + barGoLink bar(1); + bar.step(); + sLog.outString(""); + sLog.outString(">> Loaded 0 auctions. DB table `auctionhouse` is empty."); return; + } barGoLink bar( AuctionCount ); @@ -1537,24 +1660,36 @@ void ObjectMgr::LoadAuctions() aItem->bid = fields[8].GetUInt32(); aItem->startbid = fields[9].GetUInt32(); aItem->deposit = fields[10].GetUInt32(); - aItem->location = fields[11].GetUInt8(); - //check if sold item exists - if ( GetAItem( aItem->item_guidlow ) ) + + uint32 loc = fields[11].GetUInt8(); + if(!IsValidAuctionLocation(loc)) { - GetAuctionsMap( aItem->location )->AddAuction(aItem); + CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",aItem->Id); + sLog.outError("Auction %u has wrong auction location (%u)", aItem->Id, loc); + delete aItem; + continue; } - else + aItem->location = AuctionLocation(loc); + + // check if sold item exists for guid + // and item_template in fact (GetAItem will fail if problematic in result check in ObjectMgr::LoadAuctionItems) + if ( !GetAItem( aItem->item_guidlow ) ) { CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",aItem->Id); sLog.outError("Auction %u has not a existing item : %u", aItem->Id, aItem->item_guidlow); delete aItem; + continue; } + + if(aItem->location) + + GetAuctionsMap( aItem->location )->AddAuction(aItem); + } while (result->NextRow()); delete result; sLog.outString(); sLog.outString( ">> Loaded %u auctions", AuctionCount ); - sLog.outString(); } void ObjectMgr::LoadItemLocales() @@ -1653,6 +1788,32 @@ void ObjectMgr::LoadItemPrototypes() if(dbcitem) { + if(proto->Class != dbcitem->Class) + { + sLog.outErrorDb("Item (Entry: %u) not correct class %u, must be %u (still using DB value).",i,proto->Class,dbcitem->Class); + // It safe let use Class from DB + } + /* disabled: have some strange wrong cases for Subclass values. + for enable also uncomment Subclass field in ItemEntry structure and in Itemfmt[] + if(proto->SubClass != dbcitem->SubClass) + { + sLog.outErrorDb("Item (Entry: %u) not correct (Class: %u, Sub: %u) pair, must be (Class: %u, Sub: %u) (still using DB value).",i,proto->Class,proto->SubClass,dbcitem->Class,dbcitem->SubClass); + // It safe let use Subclass from DB + } + */ + + if(proto->Unk0 != dbcitem->Unk0) + { + sLog.outErrorDb("Item (Entry: %u) not correct %i Unk0, must be %i (still using DB value).",i,proto->Unk0,dbcitem->Unk0); + // It safe let use Unk0 from DB + } + + if(proto->Material != dbcitem->Material) + { + sLog.outErrorDb("Item (Entry: %u) not correct %i material, must be %i (still using DB value).",i,proto->Material,dbcitem->Material); + // It safe let use Material from DB + } + if(proto->InventoryType != dbcitem->InventoryType) { sLog.outErrorDb("Item (Entry: %u) not correct %u inventory type, must be %u (still using DB value).",i,proto->InventoryType,dbcitem->InventoryType); @@ -1678,7 +1839,7 @@ void ObjectMgr::LoadItemPrototypes() if(proto->Class >= MAX_ITEM_CLASS) { sLog.outErrorDb("Item (Entry: %u) has wrong Class value (%u)",i,proto->Class); - const_cast<ItemPrototype*>(proto)->Class = ITEM_CLASS_JUNK; + const_cast<ItemPrototype*>(proto)->Class = ITEM_CLASS_MISC; } if(proto->SubClass >= MaxItemSubclassValues[proto->Class]) @@ -1711,14 +1872,30 @@ void ObjectMgr::LoadItemPrototypes() const_cast<ItemPrototype*>(proto)->RequiredSkill = 0; } - if(!(proto->AllowableClass & CLASSMASK_ALL_PLAYABLE)) { - sLog.outErrorDb("Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped.",i,proto->AllowableClass); - } - if(!(proto->AllowableRace & RACEMASK_ALL_PLAYABLE)) - { - sLog.outErrorDb("Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped.",i,proto->AllowableRace); + // can be used in equip slot, as page read use in inventory, or spell casting at use + bool req = proto->InventoryType!=INVTYPE_NON_EQUIP || proto->PageText; + if(!req) + { + for (int j = 0; j < 5; ++j) + { + if(proto->Spells[j].SpellId) + { + req = true; + break; + } + } + } + + if(req) + { + if(!(proto->AllowableClass & CLASSMASK_ALL_PLAYABLE)) + sLog.outErrorDb("Item (Entry: %u) not have in `AllowableClass` any playable classes (%u) and can't be equipped or use.",i,proto->AllowableClass); + + if(!(proto->AllowableRace & RACEMASK_ALL_PLAYABLE)) + sLog.outErrorDb("Item (Entry: %u) not have in `AllowableRace` any playable races (%u) and can't be equipped or use.",i,proto->AllowableRace); + } } if(proto->RequiredSpell && !sSpellStore.LookupEntry(proto->RequiredSpell)) @@ -1744,11 +1921,22 @@ void ObjectMgr::LoadItemPrototypes() else if(proto->RequiredReputationRank > MIN_REPUTATION_RANK) sLog.outErrorDb("Item (Entry: %u) has RequiredReputationFaction ==0 but RequiredReputationRank > 0, rank setting is useless.",i); + if(proto->MaxCount < -1) + { + sLog.outErrorDb("Item (Entry: %u) has too large negative in maxcount (%i), replace by value (-1) no storing limits.",i,proto->MaxCount); + const_cast<ItemPrototype*>(proto)->MaxCount = -1; + } + if(proto->Stackable==0) { - sLog.outErrorDb("Item (Entry: %u) has wrong value in stackable (%u), replace by default 1.",i,proto->Stackable); + sLog.outErrorDb("Item (Entry: %u) has wrong value in stackable (%i), replace by default 1.",i,proto->Stackable); const_cast<ItemPrototype*>(proto)->Stackable = 1; } + else if(proto->Stackable < -1) + { + sLog.outErrorDb("Item (Entry: %u) has too large negative in stackable (%i), replace by value (-1) no stacking limits.",i,proto->Stackable); + const_cast<ItemPrototype*>(proto)->Stackable = -1; + } else if(proto->Stackable > 255) { sLog.outErrorDb("Item (Entry: %u) has too large value in stackable (%u), replace by hardcoded upper limit (255).",i,proto->Stackable); @@ -1775,7 +1963,7 @@ void ObjectMgr::LoadItemPrototypes() } // special format - if(proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN) + if((proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN) || (proto->Spells[0].SpellId == SPELL_ID_GENERIC_LEARN_PET)) { // spell_1 if(proto->Spells[0].SpellTrigger != ITEM_SPELLTRIGGER_ON_USE) @@ -1812,7 +2000,7 @@ void ObjectMgr::LoadItemPrototypes() const_cast<ItemPrototype*>(proto)->Spells[1].SpellTrigger = ITEM_SPELLTRIGGER_ON_USE; } // allowed only in special format - else if(proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN) + else if((proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN) || (proto->Spells[1].SpellId==SPELL_ID_GENERIC_LEARN_PET)) { sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,1+1,proto->Spells[1].SpellId); const_cast<ItemPrototype*>(proto)->Spells[0].SpellId = 0; @@ -1858,7 +2046,7 @@ void ObjectMgr::LoadItemPrototypes() const_cast<ItemPrototype*>(proto)->Spells[j].SpellId = 0; } // allowed only in special format - else if(proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN) + else if((proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN) || (proto->Spells[j].SpellId==SPELL_ID_GENERIC_LEARN_PET)) { sLog.outErrorDb("Item (Entry: %u) has broken spell in spellid_%d (%u)",i,j+1,proto->Spells[j].SpellId); const_cast<ItemPrototype*>(proto)->Spells[j].SpellId = 0; @@ -1927,17 +2115,21 @@ void ObjectMgr::LoadItemPrototypes() const_cast<ItemPrototype*>(proto)->FoodType = 0; } } - - // this DBC used currently only for check item templates in DB. - sItemStore.Clear(); } void ObjectMgr::LoadAuctionItems() { - QueryResult *result = CharacterDatabase.Query( "SELECT itemguid,item_template FROM auctionhouse" ); + // data needs to be at first place for Item::LoadFromDB + QueryResult *result = CharacterDatabase.Query( "SELECT data,itemguid,item_template FROM auctionhouse JOIN item_instance ON itemguid = guid" ); if( !result ) + { + barGoLink bar(1); + bar.step(); + sLog.outString(""); + sLog.outString(">> Loaded 0 auction items"); return; + } barGoLink bar( result->GetRowCount() ); @@ -1949,8 +2141,8 @@ void ObjectMgr::LoadAuctionItems() bar.step(); fields = result->Fetch(); - uint32 item_guid = fields[0].GetUInt32(); - uint32 item_template = fields[1].GetUInt32(); + uint32 item_guid = fields[1].GetUInt32(); + uint32 item_template = fields[2].GetUInt32(); ItemPrototype const *proto = GetItemPrototype(item_template); @@ -1962,7 +2154,7 @@ void ObjectMgr::LoadAuctionItems() Item *item = NewItemOrBag(proto); - if(!item->LoadFromDB(item_guid,0)) + if(!item->LoadFromDB(item_guid,0, result)) { delete item; continue; @@ -1972,7 +2164,6 @@ void ObjectMgr::LoadAuctionItems() ++count; } while( result->NextRow() ); - delete result; sLog.outString(); @@ -2260,7 +2451,7 @@ void ObjectMgr::LoadPlayerInfo() if(sWorld.getConfig(CONFIG_START_ALL_SPELLS)) result = WorldDatabase.Query("SELECT race, class, Spell, Active FROM playercreateinfo_spell_custom"); else - result = WorldDatabase.Query("SELECT race, class, Spell, Active FROM playercreateinfo_spell"); + result = WorldDatabase.Query("SELECT race, class, Spell FROM playercreateinfo_spell"); uint32 count = 0; @@ -2295,7 +2486,7 @@ void ObjectMgr::LoadPlayerInfo() } PlayerInfo* pInfo = &playerInfo[current_race][current_class]; - pInfo->spell.push_back(CreateSpellPair(fields[2].GetUInt16(), fields[3].GetUInt8())); + pInfo->spell.push_back(fields[2].GetUInt32()); bar.step(); ++count; @@ -2567,6 +2758,67 @@ void ObjectMgr::LoadPlayerInfo() } } } + + // Loading xp per level data + { + mPlayerXPperLevel.resize(sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + for (uint32 level = 0; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + mPlayerXPperLevel[level] = 0; + + // 0 1 + QueryResult *result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM player_xp_for_level"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar( 1 ); + + sLog.outString(); + sLog.outString( ">> Loaded %u xp for level definitions", count ); + sLog.outErrorDb( "Error loading `player_xp_for_level` table or empty table."); + exit(1); + } + + barGoLink bar( result->GetRowCount() ); + + do + { + Field* fields = result->Fetch(); + + uint32 current_level = fields[0].GetUInt32(); + uint32 current_xp = fields[1].GetUInt32(); + + if(current_level >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `player_xp_for_level` table, ignoring.", STRONG_MAX_LEVEL,current_level); + else + sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_xp_for_levels` table, ignoring.",current_level); + continue; + } + //PlayerXPperLevel + mPlayerXPperLevel[current_level] = current_xp; + bar.step(); + ++count; + } + while (result->NextRow()); + + delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u xp for level definitions", count ); + } + + // fill level gaps + for (uint32 level = 1; level < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) + { + if( mPlayerXPperLevel[level] == 0) + { + sLog.outErrorDb("Level %i does not have XP for level data. Using data of level [%i] + 100.",level+1, level); + mPlayerXPperLevel[level] = mPlayerXPperLevel[level-1]+100; + } + } } void ObjectMgr::GetPlayerClassLevelInfo(uint32 class_, uint32 level, PlayerClassLevelInfo* info) const @@ -2919,31 +3171,31 @@ void ObjectMgr::LoadQuests() QueryResult *result = WorldDatabase.Query("SELECT entry, Method, ZoneOrSort, SkillOrClass, MinLevel, QuestLevel, Type, RequiredRaces, RequiredSkillValue," // 9 10 11 12 13 14 15 16 "RepObjectiveFaction, RepObjectiveValue, RequiredMinRepFaction, RequiredMinRepValue, RequiredMaxRepFaction, RequiredMaxRepValue, SuggestedPlayers, LimitTime," - // 17 18 19 20 21 22 23 24 25 26 - "QuestFlags, SpecialFlags, CharTitleId, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell," - // 27 28 29 30 31 32 33 34 35 36 + // 17 18 19 20 21 22 23 24 25 26 27 28 + "QuestFlags, SpecialFlags, CharTitleId, PlayersSlain, BonusTalents, PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestInChain, SrcItemId, SrcItemCount, SrcSpell," + // 29 30 31 32 33 34 35 36 37 38 "Title, Details, Objectives, OfferRewardText, RequestItemsText, EndText, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4," - // 37 38 39 40 41 42 43 44 + // 39 40 41 42 43 44 45 46 "ReqItemId1, ReqItemId2, ReqItemId3, ReqItemId4, ReqItemCount1, ReqItemCount2, ReqItemCount3, ReqItemCount4," - // 45 46 47 48 49 50 51 52 53 54 54 55 + // 47 48 49 50 51 52 53 54 55 56 57 58 "ReqSourceId1, ReqSourceId2, ReqSourceId3, ReqSourceId4, ReqSourceCount1, ReqSourceCount2, ReqSourceCount3, ReqSourceCount4, ReqSourceRef1, ReqSourceRef2, ReqSourceRef3, ReqSourceRef4," - // 57 58 59 60 61 62 63 64 + // 59 60 61 62 63 64 65 66 "ReqCreatureOrGOId1, ReqCreatureOrGOId2, ReqCreatureOrGOId3, ReqCreatureOrGOId4, ReqCreatureOrGOCount1, ReqCreatureOrGOCount2, ReqCreatureOrGOCount3, ReqCreatureOrGOCount4," - // 65 66 67 68 + // 67 68 69 70 "ReqSpellCast1, ReqSpellCast2, ReqSpellCast3, ReqSpellCast4," - // 69 70 71 72 73 74 - "RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6," - // 75 76 77 78 79 80 - "RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6," - // 81 82 83 84 85 86 87 88 + // 71 72 73 74 75 76 77 + "RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6, RewChoiceItemId7," + // 78 79 80 81 82 83 84 + "RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6, RewChoiceItemCount7," + // 85 86 87 88 89 90 91 92 "RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4," - // 89 90 91 92 93 94 95 96 97 98 + // 93 94 95 96 97 98 99 100 101 102 "RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5," - // 99 100 101 102 103 104 105 106 107 108 109 + // 103 104 105 106 107 108 109 110 111 112 113 "RewHonorableKills, RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt," - // 110 111 112 113 114 115 116 117 118 119 - "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4,IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4," - // 120 121 + // 114 115 116 117 118 119 120 121 122 123 + "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4,IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4," + // 124 125 "StartScript, CompleteScript" " FROM quest_template"); if(result == NULL) @@ -4296,14 +4548,20 @@ void ObjectMgr::LoadInstanceTemplate() else if(!entry->HasResetTime()) continue; + //FIXME: now exist heroic instance, normal/heroic raid instances + // entry->resetTimeHeroic store reset time for both heroic mode instance (raid and non-raid) + // entry->resetTimeRaid store reset time for normal raid only + // for current state entry->resetTimeRaid == entry->resetTimeHeroic in case raid instances with heroic mode. + // but at some point wee need implement reset time dependen from raid insatance mode if(temp->reset_delay == 0) { // use defaults from the DBC - if(entry->SupportsHeroicMode()) + if(entry->resetTimeHeroic) // for both raid and non raids, read above { temp->reset_delay = entry->resetTimeHeroic / DAY; } else if (entry->resetTimeRaid && entry->map_type == MAP_RAID) + // for normal raid only { temp->reset_delay = entry->resetTimeRaid / DAY; } @@ -4481,14 +4739,27 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) // 0 1 2 3 4 5 6 7 8 9 QueryResult* result = CharacterDatabase.PQuery("SELECT id,messageType,sender,receiver,itemTextId,has_items,expire_time,cod,checked,mailTemplateId FROM mail WHERE expire_time < '" I64FMTD "'", (uint64)basetime); if ( !result ) + { + barGoLink bar(1); + bar.step(); + sLog.outString(""); + sLog.outString(">> Only expired mails (need to be return or delete) or DB table `mail` is empty."); return; // any mails need to be returned or deleted - Field *fields; + } + //std::ostringstream delitems, delmails; //will be here for optimization //bool deletemail = false, deleteitem = false; //delitems << "DELETE FROM item_instance WHERE guid IN ( "; //delmails << "DELETE FROM mail WHERE id IN ( " + + barGoLink bar( result->GetRowCount() ); + uint32 count = 0; + Field *fields; + do { + bar.step(); + fields = result->Fetch(); Mail *m = new Mail; m->messageID = fields[0].GetUInt32(); @@ -4554,8 +4825,12 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) //delmails << m->messageID << ", "; CharacterDatabase.PExecute("DELETE FROM mail WHERE id = '%u'", m->messageID); delete m; + ++count; } while (result->NextRow()); delete result; + + sLog.outString(); + sLog.outString( ">> Loaded %u mails", count ); } void ObjectMgr::LoadQuestAreaTriggers() @@ -4712,7 +4987,7 @@ void ObjectMgr::LoadAreaTriggerScripts() sLog.outString( ">> Loaded %u areatrigger scripts", count ); } -uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid ) +uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid, uint32 team ) { bool found = false; float dist; @@ -4721,24 +4996,31 @@ uint32 ObjectMgr::GetNearestTaxiNode( float x, float y, float z, uint32 mapid ) for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) { TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(i); - if(node && node->map_id == mapid) + if(!node || node->map_id != mapid || !node->MountCreatureID[team == ALLIANCE ? 1 : 0]) + continue; + + uint8 field = (uint8)((i - 1) / 32); + uint32 submask = 1<<((i-1)%32); + + // skip not taxi network nodes + if((sTaxiNodesMask[field] & submask)==0) + continue; + + float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z); + if(found) { - float dist2 = (node->x - x)*(node->x - x)+(node->y - y)*(node->y - y)+(node->z - z)*(node->z - z); - if(found) + if(dist2 < dist) { - if(dist2 < dist) - { - dist = dist2; - id = i; - } - } - else - { - found = true; dist = dist2; id = i; } } + else + { + found = true; + dist = dist2; + id = i; + } } return id; @@ -4776,17 +5058,19 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team ) TaxiNodesEntry const* node = sTaxiNodesStore.LookupEntry(id); if(node) { - if (team == ALLIANCE) mount_entry = node->alliance_mount_type; - else mount_entry = node->horde_mount_type; - - CreatureInfo const *cinfo = GetCreatureTemplate(mount_entry); - if (cinfo) + if (team == ALLIANCE) { - if(! (mount_id = cinfo->GetRandomValidModelId())) - { - sLog.outErrorDb("No displayid found for the taxi mount with the entry %u! Can't load it!", mount_entry); - return false; - } + mount_entry = node->MountCreatureID[1]; + CreatureInfo const *ci = GetCreatureTemplate(mount_entry); + if(ci) + mount_id = ci->Modelid1; + } + if (team == HORDE) + { + mount_entry = node->MountCreatureID[0]; + CreatureInfo const *ci = GetCreatureTemplate(mount_entry); + if(ci) + mount_id = ci->Modelid3; } } @@ -4914,7 +5198,7 @@ void ObjectMgr::LoadGraveyardZones() WorldSafeLocsEntry const *ObjectMgr::GetClosestGraveYard(float x, float y, float z, uint32 MapId, uint32 team) { // search for zone associated closest graveyard - uint32 zoneId = MapManager::Instance().GetZoneId(MapId,x,y); + uint32 zoneId = MapManager::Instance().GetZoneId(MapId,x,y,z); // Simulate std. algorithm: // found some graveyard associated to (ghost_zone,ghost_map) @@ -5242,6 +5526,9 @@ void ObjectMgr::LoadAreaTriggerTeleports() sLog.outString( ">> Loaded %u area trigger teleport definitions", count ); } +/* + * Searches for the areatrigger which teleports players out of the given map + */ AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const { const MapEntry *mapEntry = sMapStore.LookupEntry(Map); @@ -5258,6 +5545,23 @@ AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const return NULL; } +/** + * Searches for the areatrigger which teleports players to the given map + */ +AreaTrigger const* ObjectMgr::GetMapEntranceTrigger(uint32 Map) const +{ + for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); ++itr) + { + if(itr->second.target_mapId == Map) + { + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(itr->first); + if(atEntry) + return &itr->second; + } + } + return NULL; +} + void ObjectMgr::SetHighestGuids() { QueryResult *result = CharacterDatabase.Query( "SELECT MAX(guid) FROM characters" ); @@ -5274,9 +5578,6 @@ void ObjectMgr::SetHighestGuids() delete result; } - // pet guids are not saved to DB, set to 0 (pet guid != pet id) - m_hiPetGuid = 0; - result = CharacterDatabase.Query( "SELECT MAX(guid) FROM item_instance" ); if( result ) { @@ -5429,6 +5730,13 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) World::StopNow(ERROR_EXIT_CODE); } return m_hiPetGuid++; + case HIGHGUID_VEHICLE: + if(m_hiVehicleGuid>=0x00FFFFFF) + { + sLog.outError("Vehicle guid overflow!! Can't continue, shutting down server. "); + World::StopNow(ERROR_EXIT_CODE); + } + return m_hiVehicleGuid++; case HIGHGUID_PLAYER: if(m_hiCharGuid>=0xFFFFFFFE) { @@ -5616,10 +5924,10 @@ void ObjectMgr::LoadGameobjectInfo() break; } case GAMEOBJECT_TYPE_CHAIR: //7 - if(goInfo->chair.height > 2) + if(goInfo->chair.height > (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR) ) { - sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..2.", - id,goInfo->type,goInfo->chair.height); + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..%i.", + id,goInfo->type,goInfo->chair.height,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR); // prevent client and server unexpected work const_cast<GameObjectInfo*>(goInfo)->chair.height = 0; @@ -5714,6 +6022,16 @@ void ObjectMgr::LoadGameobjectInfo() } break; } + case GAMEOBJECT_TYPE_BARBER_CHAIR: //32 + if(goInfo->barberChair.chairheight > (UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR) ) + { + sLog.outErrorDb("Gameobject (Entry: %u GoType: %u) have data1=%u but correct chair height in range 0..%i.", + id,goInfo->type,goInfo->barberChair.chairheight,UNIT_STAND_STATE_SIT_HIGH_CHAIR-UNIT_STAND_STATE_SIT_LOW_CHAIR); + + // prevent client and server unexpected work + const_cast<GameObjectInfo*>(goInfo)->barberChair.chairheight = 0; + } + break; } } @@ -5762,6 +6080,13 @@ uint32 ObjectMgr::GetBaseXP(uint32 level) return mBaseXPTable[level] ? mBaseXPTable[level] : 0; } +uint32 ObjectMgr::GetXPForLevel(uint32 level) +{ + if (level < mPlayerXPperLevel.size()) + return mPlayerXPperLevel[level]; + return 0; +} + void ObjectMgr::LoadPetNames() { uint32 count = 0; @@ -6230,11 +6555,18 @@ void ObjectMgr::LoadReservedPlayersNames() bar.step(); fields = result->Fetch(); std::string name= fields[0].GetCppString(); - if(normalizePlayerName(name)) + + std::wstring wstr; + if(!Utf8toWStr (name,wstr)) { - m_ReservedNames.insert(name); - ++count; + sLog.outError("Table `reserved_name` have invalid name: %s", name.c_str() ); + continue; } + + wstrToLower(wstr); + + m_ReservedNames.insert(wstr); + ++count; } while ( result->NextRow() ); delete result; @@ -6243,6 +6575,17 @@ void ObjectMgr::LoadReservedPlayersNames() sLog.outString( ">> Loaded %u reserved player names", count ); } +bool ObjectMgr::IsReservedName( const std::string& name ) const +{ + std::wstring wstr; + if(!Utf8toWStr (name,wstr)) + return false; + + wstrToLower(wstr); + + return m_ReservedNames.find(wstr) != m_ReservedNames.end(); +} + enum LanguageType { LT_BASIC_LATIN = 0x0000, @@ -6391,55 +6734,26 @@ int ObjectMgr::GetOrNewIndexForLocale( LocaleConstant loc ) return m_LocalForIndex.size()-1; } -void ObjectMgr::LoadBattleMastersEntry() +void ObjectMgr::LoadGameObjectForQuests() { - mBattleMastersMap.clear(); // need for reload case - - QueryResult *result = WorldDatabase.Query( "SELECT entry,bg_template FROM battlemaster_entry" ); - - uint32 count = 0; + mGameObjectForQuestSet.clear(); // need for reload case - if( !result ) + if( !sGOStorage.MaxEntry ) { barGoLink bar( 1 ); bar.step(); - sLog.outString(); - sLog.outString( ">> Loaded 0 battlemaster entries - table is empty!" ); + sLog.outString( ">> Loaded 0 GameObjects for quests" ); return; } - barGoLink bar( result->GetRowCount() ); - - do - { - ++count; - bar.step(); - - Field *fields = result->Fetch(); - - uint32 entry = fields[0].GetUInt32(); - uint32 bgTypeId = fields[1].GetUInt32(); - - mBattleMastersMap[entry] = bgTypeId; - - } while( result->NextRow() ); - - delete result; - - sLog.outString(); - sLog.outString( ">> Loaded %u battlemaster entries", count ); -} - -void ObjectMgr::LoadGameObjectForQuests() -{ - mGameObjectForQuestSet.clear(); // need for reload case - + barGoLink bar( sGOStorage.MaxEntry - 1 ); uint32 count = 0; // collect GO entries for GO that must activated for(uint32 go_entry = 1; go_entry < sGOStorage.MaxEntry; ++go_entry) { + bar.step(); GameObjectInfo const* goInfo = sGOStorage.LookupEntry<GameObjectInfo>(go_entry); if(!goInfo) continue; @@ -6474,7 +6788,7 @@ void ObjectMgr::LoadGameObjectForQuests() } sLog.outString(); - sLog.outString( ">> Loaded %u GameObject for quests", count ); + sLog.outString( ">> Loaded %u GameObjects for quests", count ); } bool ObjectMgr::LoadTrinityStrings(DatabaseType& db, char const* table, int32 min_value, int32 max_value) @@ -6767,7 +7081,7 @@ bool PlayerCondition::Meets(Player const * player) const { Unit::AuraMap const& auras = player->GetAuras(); for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual==3580) + if((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual[0]==3580) return true; return false; } @@ -6944,7 +7258,7 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial) return SKILL_RANGE_MONO; case SKILL_CATEGORY_ARMOR: case SKILL_CATEGORY_CLASS: - if(pSkill->id != SKILL_POISONS && pSkill->id != SKILL_LOCKPICKING) + if(pSkill->id != SKILL_LOCKPICKING) return SKILL_RANGE_MONO; else return SKILL_RANGE_LEVEL; @@ -6959,7 +7273,7 @@ SkillRangeType GetSkillRangeType(SkillLineEntry const *pSkill, bool racial) return SKILL_RANGE_MONO; default: case SKILL_CATEGORY_ATTRIBUTES: //not found in dbc - case SKILL_CATEGORY_NOT_DISPLAYED: //only GENEREC(DND) + case SKILL_CATEGORY_GENERIC: //only GENERIC(DND) return SKILL_RANGE_NONE; } } @@ -7020,11 +7334,10 @@ void ObjectMgr::LoadGameTele() ++count; } while (result->NextRow()); - delete result; sLog.outString(); - sLog.outString( ">> Loaded %u game tele's", count ); + sLog.outString( ">> Loaded %u GameTeleports", count ); } GameTele const* ObjectMgr::GetGameTele(const std::string& name) const @@ -7162,14 +7475,27 @@ void ObjectMgr::LoadTrainerSpell() TrainerSpell* pTrainerSpell = new TrainerSpell(); pTrainerSpell->spell = spell; - pTrainerSpell->spellcost = fields[2].GetUInt32(); - pTrainerSpell->reqskill = fields[3].GetUInt32(); - pTrainerSpell->reqskillvalue = fields[4].GetUInt32(); - pTrainerSpell->reqlevel = fields[5].GetUInt32(); + pTrainerSpell->spellCost = fields[2].GetUInt32(); + pTrainerSpell->reqSkill = fields[3].GetUInt32(); + pTrainerSpell->reqSkillValue = fields[4].GetUInt32(); + pTrainerSpell->reqLevel = fields[5].GetUInt32(); - if(!pTrainerSpell->reqlevel) - pTrainerSpell->reqlevel = spellinfo->spellLevel; + if(!pTrainerSpell->reqLevel) + pTrainerSpell->reqLevel = spellinfo->spellLevel; + + // calculate learned spell for profession case when stored cast-spell + pTrainerSpell->learnedSpell = spell; + for(int i = 0; i <3; ++i) + { + if(spellinfo->Effect[i]!=SPELL_EFFECT_LEARN_SPELL) + continue; + if(SpellMgr::IsProfessionOrRidingSpell(spellinfo->EffectTriggerSpell[i])) + { + pTrainerSpell->learnedSpell = spellinfo->EffectTriggerSpell[i]; + break; + } + } TrainerSpellData& data = m_mCacheTrainerSpellMap[entry]; @@ -7183,7 +7509,7 @@ void ObjectMgr::LoadTrainerSpell() delete result; sLog.outString(); - sLog.outString( ">> Loaded Trainers %d", count ); + sLog.outString( ">> Loaded %d Trainers", count ); } void ObjectMgr::LoadVendors() @@ -7461,16 +7787,30 @@ void ObjectMgr::LoadScriptNames() "SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' " "UNION " "SELECT DISTINCT(script) FROM instance_template WHERE script <> ''"); - if(result) + + if( !result ) { - do - { - m_scriptNames.push_back((*result)[0].GetString()); - } while (result->NextRow()); - delete result; + barGoLink bar( 1 ); + bar.step(); + sLog.outString(); + sLog.outErrorDb(">> Loaded empty set of Script Names!"); + return; } + barGoLink bar( result->GetRowCount() ); + uint32 count = 0; + + do + { + bar.step(); + m_scriptNames.push_back((*result)[0].GetString()); + ++count; + } while (result->NextRow()); + delete result; + std::sort(m_scriptNames.begin(), m_scriptNames.end()); + sLog.outString(); + sLog.outString( ">> Loaded %d Script Names", count ); } uint32 ObjectMgr::GetScriptId(const char *name) diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 7d7a419d923..99cd9a5d573 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -399,15 +399,15 @@ class ObjectMgr mAitems.erase(i); return true; } - AuctionHouseObject * GetAuctionsMap( uint32 location ); + AuctionHouseObject * GetAuctionsMap( AuctionLocation location ); //auction messages void SendAuctionWonMail( AuctionEntry * auction ); void SendAuctionSalePendingMail( AuctionEntry * auction ); void SendAuctionSuccessfulMail( AuctionEntry * auction ); void SendAuctionExpiredMail( AuctionEntry * auction ); - static uint32 GetAuctionCut( uint32 location, uint32 highBid ); - static uint32 GetAuctionDeposit(uint32 location, uint32 time, Item *pItem); + static uint32 GetAuctionCut( AuctionLocation location, uint32 highBid ); + static uint32 GetAuctionDeposit(AuctionLocation location, uint32 time, Item *pItem); static uint32 GetAuctionOutBid(uint32 currentBid); PetLevelInfo const* GetPetLevelInfo(uint32 creature_id, uint32 level) const; @@ -435,7 +435,7 @@ class ObjectMgr uint32 GetPlayerAccountIdByGUID(const uint64 &guid) const; uint32 GetPlayerAccountIdByPlayerName(const std::string& name) const; - uint32 GetNearestTaxiNode( float x, float y, float z, uint32 mapid ); + uint32 GetNearestTaxiNode( float x, float y, float z, uint32 mapid, uint32 team ); void GetTaxiPath( uint32 source, uint32 destination, uint32 &path, uint32 &cost); uint16 GetTaxiMount( uint32 id, uint32 team ); void GetTaxiPathNodes( uint32 path, Path &pathnodes, std::vector<uint32>& mapIds ); @@ -465,14 +465,6 @@ class ObjectMgr return false; } - uint32 GetBattleMasterBG(uint32 entry) const - { - BattleMastersMap::const_iterator itr = mBattleMastersMap.find(entry); - if(itr != mBattleMastersMap.end()) - return itr->second; - return 2; //BATTLEGROUND_WS - i will not add include only for constant usage! - } - void AddGossipText(GossipText *pGText); GossipText *GetGossipText(uint32 Text_ID); @@ -491,6 +483,7 @@ class ObjectMgr } AreaTrigger const* GetGoBackTrigger(uint32 Map) const; + AreaTrigger const* GetMapEntranceTrigger(uint32 Map) const; uint32 GetAreaTriggerScriptId(uint32 trigger_id); @@ -568,7 +561,6 @@ class ObjectMgr void LoadQuestAreaTriggers(); void LoadAreaTriggerScripts(); void LoadTavernAreaTriggers(); - void LoadBattleMastersEntry(); void LoadGameObjectForQuests(); void LoadItemTexts(); @@ -597,6 +589,7 @@ class ObjectMgr std::string GeneratePetName(uint32 entry); uint32 GetBaseXP(uint32 level); + uint32 GetXPForLevel(uint32 level); int32 GetFishingBaseSkillLevel(uint32 entry) const { @@ -734,10 +727,7 @@ class ObjectMgr // reserved names void LoadReservedPlayersNames(); - bool IsReservedName(const std::string& name) const - { - return m_ReservedNames.find(name) != m_ReservedNames.end(); - } + bool IsReservedName(const std::string& name) const; // name with valid structure and symbols static bool IsValidName( const std::string& name, bool create = false ); @@ -811,6 +801,8 @@ class ObjectMgr ScriptNameMap &GetScriptNames() { return m_scriptNames; } const char * GetScriptName(uint32 id) { return id < m_scriptNames.size() ? m_scriptNames[id].c_str() : ""; } uint32 GetScriptId(const char *name); + + int GetOrNewIndexForLocale(LocaleConstant loc); protected: // first free id for selected id type @@ -825,6 +817,7 @@ class ObjectMgr uint32 m_hiCharGuid; uint32 m_hiCreatureGuid; uint32 m_hiPetGuid; + uint32 m_hiVehicleGuid; uint32 m_hiItemGuid; uint32 m_hiGoGuid; uint32 m_hiDoGuid; @@ -834,7 +827,6 @@ class ObjectMgr typedef UNORDERED_MAP<uint32, GossipText*> GossipTextMap; typedef UNORDERED_MAP<uint32, uint32> QuestAreaTriggerMap; - typedef UNORDERED_MAP<uint32, uint32> BattleMastersMap; typedef UNORDERED_MAP<uint32, std::string> ItemTextMap; typedef std::set<uint32> TavernAreaTriggerSet; typedef std::set<uint32> GameObjectForQuestSet; @@ -853,7 +845,6 @@ class ObjectMgr AuctionHouseObject mNeutralAuctions; QuestAreaTriggerMap mQuestAreaTriggerMap; - BattleMastersMap mBattleMastersMap; TavernAreaTriggerSet mTavernAreaTriggerSet; GameObjectForQuestSet mGameObjectForQuestSet; GossipTextMap mGossipText; @@ -867,7 +858,7 @@ class ObjectMgr PetCreateSpellMap mPetCreateSpell; //character reserved names - typedef std::set<std::string> ReservedNamesMap; + typedef std::set<std::wstring> ReservedNamesMap; ReservedNamesMap m_ReservedNames; std::set<uint32> m_DisabledPlayerSpells; @@ -881,7 +872,6 @@ class ObjectMgr typedef std::vector<LocaleConstant> LocalForIndex; LocalForIndex m_LocalForIndex; - int GetOrNewIndexForLocale(LocaleConstant loc); int DBCLocaleIndex; @@ -900,6 +890,9 @@ class ObjectMgr void BuildPlayerLevelInfo(uint8 race, uint8 class_, uint8 level, PlayerLevelInfo* plinfo) const; PlayerInfo playerInfo[MAX_RACES][MAX_CLASSES]; + typedef std::vector<uint32> PlayerXPperLevel; // [level] + PlayerXPperLevel mPlayerXPperLevel; + typedef std::map<uint32,uint32> BaseXPMap; // [area level][base xp] BaseXPMap mBaseXPTable; diff --git a/src/game/ObjectPosSelector.cpp b/src/game/ObjectPosSelector.cpp new file mode 100644 index 00000000000..899dfec3fdb --- /dev/null +++ b/src/game/ObjectPosSelector.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ObjectPosSelector.h" + +ObjectPosSelector::ObjectPosSelector(float x,float y,float size,float dist) +: m_center_x(x),m_center_y(y),m_size(size),m_dist(dist) +{ + m_anglestep = acos(m_dist/(m_dist+2*m_size)); + + m_nextUsedPos[USED_POS_PLUS] = m_UsedPosLists[USED_POS_PLUS].end(); + m_nextUsedPos[USED_POS_MINUS] = m_UsedPosLists[USED_POS_MINUS].end(); + + m_smallStepAngle[USED_POS_PLUS] = 0; + m_smallStepAngle[USED_POS_MINUS] = 0; + + m_smallStepOk[USED_POS_PLUS] = false; + m_smallStepOk[USED_POS_MINUS] = false; + + m_smallStepNextUsedPos[USED_POS_PLUS] = NULL; + m_smallStepNextUsedPos[USED_POS_MINUS] = NULL; +} + +ObjectPosSelector::UsedPosList::value_type const* ObjectPosSelector::nextUsedPos(UsedPosType uptype) +{ + UsedPosList::const_iterator itr = m_nextUsedPos[uptype]; + if(itr!=m_UsedPosLists[uptype].end()) + ++itr; + + if(itr==m_UsedPosLists[uptype].end()) + { + if(!m_UsedPosLists[~uptype].empty()) + return &*m_UsedPosLists[~uptype].rbegin(); + else + return NULL; + } + else + return &*itr; +} + +void ObjectPosSelector::AddUsedPos(float size,float angle,float dist) +{ + if(angle>=0) + m_UsedPosLists[USED_POS_PLUS].insert(UsedPosList::value_type(angle,UsedPos(1.0,size,dist))); + else + m_UsedPosLists[USED_POS_MINUS].insert(UsedPosList::value_type(-angle,UsedPos(-1.0,size,dist))); +} + +void ObjectPosSelector::InitializeAngle() +{ + m_nextUsedPos[USED_POS_PLUS] = m_UsedPosLists[USED_POS_PLUS].begin(); + m_nextUsedPos[USED_POS_MINUS] = m_UsedPosLists[USED_POS_MINUS].begin(); + + m_smallStepAngle[USED_POS_PLUS] = 0; + m_smallStepAngle[USED_POS_MINUS] = 0; + + m_smallStepOk[USED_POS_PLUS] = true; + m_smallStepOk[USED_POS_MINUS] = true; +} + +bool ObjectPosSelector::FirstAngle(float& angle) +{ + if(m_UsedPosLists[USED_POS_PLUS].empty() && !m_UsedPosLists[USED_POS_MINUS].empty() ) + return NextAngleFor(*m_UsedPosLists[USED_POS_MINUS].begin(),1.0,USED_POS_PLUS,angle); + else if(m_UsedPosLists[USED_POS_MINUS].empty() && !m_UsedPosLists[USED_POS_PLUS].empty() ) + return NextAngleFor(*m_UsedPosLists[USED_POS_PLUS].begin(),-1.0,USED_POS_MINUS,angle); + + return false; +} + +bool ObjectPosSelector::NextAngle(float& angle) +{ + while(m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() || + m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end() || + m_smallStepOk[USED_POS_PLUS] || m_smallStepOk[USED_POS_MINUS] ) + { + // calculate next possible angle + if(NextPosibleAngle(angle)) + return true; + } + + return false; +} + +bool ObjectPosSelector::NextUsedAngle(float& angle) +{ + while(m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() || + m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end() ) + { + // calculate next possible angle + if(!NextPosibleAngle(angle)) + return true; + } + + return false; +} + +bool ObjectPosSelector::NextPosibleAngle( float& angle ) +{ + // ++ direction less updated + if( m_nextUsedPos[USED_POS_PLUS]!=m_UsedPosLists[USED_POS_PLUS].end() && + (m_nextUsedPos[USED_POS_MINUS]==m_UsedPosLists[USED_POS_MINUS].end() || m_nextUsedPos[USED_POS_PLUS]->first <= m_nextUsedPos[USED_POS_MINUS]->first) ) + { + bool ok; + if(m_smallStepOk[USED_POS_PLUS]) + ok = NextSmallStepAngle(1.0,USED_POS_PLUS,angle); + else + ok = NextAngleFor(*m_nextUsedPos[USED_POS_PLUS],1.0,USED_POS_PLUS,angle); + + if(!ok) + ++m_nextUsedPos[USED_POS_PLUS]; // increase. only at fail (original or checked) + return ok; + } + // -- direction less updated + else if( m_nextUsedPos[USED_POS_MINUS]!=m_UsedPosLists[USED_POS_MINUS].end()) + { + bool ok; + if(m_smallStepOk[USED_POS_MINUS]) + ok = NextSmallStepAngle(-1.0,USED_POS_MINUS,angle); + else + ok = NextAngleFor(*m_nextUsedPos[USED_POS_MINUS],-1.0,USED_POS_MINUS,angle); + + if(!ok) + ++m_nextUsedPos[USED_POS_MINUS]; + return ok; + } + else // both list empty + { + if( m_smallStepOk[USED_POS_PLUS] && (!m_smallStepOk[USED_POS_MINUS] || m_smallStepAngle[USED_POS_PLUS] <= m_smallStepAngle[USED_POS_MINUS]) ) + { + return NextSmallStepAngle(1.0,USED_POS_PLUS,angle); + } + // -- direction less updated + else if( m_smallStepOk[USED_POS_MINUS] ) + { + return NextSmallStepAngle(-1.0,USED_POS_MINUS,angle); + } + } + + // no angles + return false; +} diff --git a/src/game/ObjectPosSelector.h b/src/game/ObjectPosSelector.h new file mode 100644 index 00000000000..84050611121 --- /dev/null +++ b/src/game/ObjectPosSelector.h @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _OBJECT_POS_SELECTOR_H +#define _OBJECT_POS_SELECTOR_H + +#include<Common.h> + +#include<map> + +enum UsedPosType { USED_POS_PLUS, USED_POS_MINUS }; + +inline UsedPosType operator ~(UsedPosType uptype) +{ + return uptype==USED_POS_PLUS ? USED_POS_MINUS : USED_POS_PLUS; +} + +struct ObjectPosSelector +{ + struct UsedPos + { + UsedPos(float sign_, float size_,float dist_) : sign(sign_), size(size_),dist(dist_) {} + + float sign; + + float size; // size of point + float dist; // dist to central point (including central point size) + }; + + typedef std::multimap<float,UsedPos> UsedPosList; // abs(angle)->Node + + ObjectPosSelector(float x,float y,float size,float dist); + + void AddUsedPos(float size,float angle,float dist); + void InitializeAngle(); + + bool FirstAngle(float& angle); + bool NextAngle(float& angle); + bool NextUsedAngle(float& angle); + + bool NextPosibleAngle( float& angle ); + + bool CheckAngle(UsedPosList::value_type const& nextUsedPos, float sign, float angle ) const + { + float angle_step2 = GetAngle(nextUsedPos.second); + + float next_angle = nextUsedPos.first; + if(nextUsedPos.second.sign * sign < 0) // last node from diff. list (-pi+alpha) + next_angle = 2*M_PI-next_angle; // move to positive + + return fabs(angle)+angle_step2 <= next_angle; + } + + bool CheckOriginal() const + { + return (m_UsedPosLists[USED_POS_PLUS].empty() || CheckAngle( *m_UsedPosLists[USED_POS_PLUS].begin(),1.0,0)) && + (m_UsedPosLists[USED_POS_MINUS].empty() || CheckAngle( *m_UsedPosLists[USED_POS_MINUS].begin(),-1.0,0)); + } + + bool IsNonBalanced() const { return m_UsedPosLists[USED_POS_PLUS].empty() != m_UsedPosLists[USED_POS_MINUS].empty(); } + + bool NextAngleFor( UsedPosList::value_type const& usedPos, float sign, UsedPosType uptype, float &angle ) + { + float angle_step = GetAngle(usedPos.second); + + // next possible angle + angle = usedPos.first * usedPos.second.sign + angle_step * sign; + + UsedPosList::value_type const* nextNode = nextUsedPos(uptype); + if(nextNode) + { + // if next node permit use selected angle, then do it + if(!CheckAngle(*nextNode, sign, angle)) + { + m_smallStepOk[uptype] = false; + return false; + } + } + + // possible more points + m_smallStepOk[uptype] = true; + m_smallStepAngle[uptype] = angle; + m_smallStepNextUsedPos[uptype] = nextNode; + + return true; + } + + bool NextSmallStepAngle( float sign, UsedPosType uptype, float &angle ) + { + // next possible angle + angle = m_smallStepAngle[uptype] + m_anglestep * sign; + + if(fabs(angle) > M_PI) + { + m_smallStepOk[uptype] = false; + return false; + } + + if(m_smallStepNextUsedPos[uptype]) + { + if(fabs(angle) >= m_smallStepNextUsedPos[uptype]->first) + { + m_smallStepOk[uptype] = false; + return false; + } + + // if next node permit use selected angle, then do it + if(!CheckAngle(*m_smallStepNextUsedPos[uptype], sign, angle)) + { + m_smallStepOk[uptype] = false; + return false; + } + } + + // possible more points + m_smallStepAngle[uptype] = angle; + return true; + } + + // next used post for m_nextUsedPos[uptype] + UsedPosList::value_type const* nextUsedPos(UsedPosType uptype); + + // angle from used pos to next possible free pos + float GetAngle(UsedPos const& usedPos) const { return acos(m_dist/(usedPos.dist+usedPos.size+m_size)); } + + float m_center_x; + float m_center_y; + float m_size; // size of object in center + float m_dist; // distance for searching pos (including central object size) + float m_anglestep; + + UsedPosList m_UsedPosLists[2]; + UsedPosList::const_iterator m_nextUsedPos[2]; + + // field for small step from first after next used pos until next pos + float m_smallStepAngle[2]; + bool m_smallStepOk[2]; + UsedPosList::value_type const* m_smallStepNextUsedPos[2]; +}; +#endif diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 7012ea04fb6..78fdeb8d0ce 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,1064 +28,1201 @@ /// Correspondence between opcodes and their names OpcodeHandler opcodeTable[NUM_MSG_TYPES] = { - /*0x000*/ { "MSG_NULL_ACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x001*/ { "CMSG_BOOTME", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x002*/ { "CMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x003*/ { "SMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x004*/ { "CMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x005*/ { "SMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x006*/ { "CMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x007*/ { "SMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x008*/ { "CMSG_WORLD_TELEPORT", STATUS_LOGGEDIN, &WorldSession::HandleWorldTeleportOpcode }, - /*0x009*/ { "CMSG_TELEPORT_TO_UNIT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, - /*0x00A*/ { "CMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00B*/ { "SMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x00C*/ { "CMSG_DEBUG_CHANGECELLZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00D*/ { "CMSG_EMBLAZON_TABARD_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00E*/ { "CMSG_UNEMBLAZON_TABARD_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x00F*/ { "CMSG_RECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x010*/ { "CMSG_LEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x011*/ { "CMSG_CREATEMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x012*/ { "CMSG_DESTROYMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x013*/ { "CMSG_CREATEITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x014*/ { "CMSG_CREATEGAMEOBJECT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x015*/ { "SMSG_CHECK_FOR_BOTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x016*/ { "CMSG_MAKEMONSTERATTACKGUID", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x017*/ { "CMSG_BOT_DETECTED2", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x018*/ { "CMSG_FORCEACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x019*/ { "CMSG_FORCEACTIONONOTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x01A*/ { "CMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x01B*/ { "SMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x01C*/ { "CMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x01D*/ { "SMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x01E*/ { "SMSG_DEBUGINFOSPELLMISS_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x01F*/ { "CMSG_WEATHER_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x020*/ { "CMSG_UNDRESSPLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x021*/ { "CMSG_BEASTMASTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x022*/ { "CMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x023*/ { "SMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x024*/ { "CMSG_CHEAT_SETMONEY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x025*/ { "CMSG_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x026*/ { "CMSG_PET_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x027*/ { "CMSG_SET_WORLDSTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x028*/ { "CMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x029*/ { "CMSG_USE_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02A*/ { "CMSG_FLAG_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02B*/ { "CMSG_FLAG_QUEST_FINISH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02C*/ { "CMSG_CLEAR_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02D*/ { "CMSG_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02E*/ { "CMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x02F*/ { "SMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x030*/ { "CMSG_DISABLE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x031*/ { "CMSG_ADVANCE_SPAWN_TIME", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x032*/ { "CMSG_PVP_PORT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x033*/ { "CMSG_AUTH_SRP6_BEGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x034*/ { "CMSG_AUTH_SRP6_PROOF", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x035*/ { "CMSG_AUTH_SRP6_RECODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x036*/ { "CMSG_CHAR_CREATE", STATUS_AUTHED, &WorldSession::HandleCharCreateOpcode }, - /*0x037*/ { "CMSG_CHAR_ENUM", STATUS_AUTHED, &WorldSession::HandleCharEnumOpcode }, - /*0x038*/ { "CMSG_CHAR_DELETE", STATUS_AUTHED, &WorldSession::HandleCharDeleteOpcode }, - /*0x039*/ { "SMSG_AUTH_SRP6_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03A*/ { "SMSG_CHAR_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03B*/ { "SMSG_CHAR_ENUM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03C*/ { "SMSG_CHAR_DELETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03D*/ { "CMSG_PLAYER_LOGIN", STATUS_AUTHED, &WorldSession::HandlePlayerLoginOpcode }, - /*0x03E*/ { "SMSG_NEW_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x03F*/ { "SMSG_TRANSFER_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x040*/ { "SMSG_TRANSFER_ABORTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x041*/ { "SMSG_CHARACTER_LOGIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x042*/ { "SMSG_LOGIN_SETTIMESPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x043*/ { "SMSG_GAMETIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x044*/ { "CMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x045*/ { "SMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x046*/ { "CMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x047*/ { "SMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x048*/ { "CMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x049*/ { "SMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x04A*/ { "CMSG_PLAYER_LOGOUT", STATUS_LOGGEDIN, &WorldSession::HandlePlayerLogoutOpcode }, - /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLogoutRequestOpcode }, - /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleLogoutCancelOpcode }, - /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNameQueryOpcode }, - /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x052*/ { "CMSG_PET_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetNameQuery }, - /*0x053*/ { "SMSG_PET_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x054*/ { "CMSG_GUILD_QUERY", STATUS_AUTHED, &WorldSession::HandleGuildQueryOpcode }, - /*0x055*/ { "SMSG_GUILD_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x056*/ { "CMSG_ITEM_QUERY_SINGLE", STATUS_LOGGEDIN, &WorldSession::HandleItemQuerySingleOpcode }, - /*0x057*/ { "CMSG_ITEM_QUERY_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x058*/ { "SMSG_ITEM_QUERY_SINGLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x059*/ { "SMSG_ITEM_QUERY_MULTIPLE_RESPONSE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x05A*/ { "CMSG_PAGE_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePageQueryOpcode }, - /*0x05B*/ { "SMSG_PAGE_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x05C*/ { "CMSG_QUEST_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestQueryOpcode }, - /*0x05D*/ { "SMSG_QUEST_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x05E*/ { "CMSG_GAMEOBJECT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectQueryOpcode }, - /*0x05F*/ { "SMSG_GAMEOBJECT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x060*/ { "CMSG_CREATURE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCreatureQueryOpcode }, - /*0x061*/ { "SMSG_CREATURE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x062*/ { "CMSG_WHO", STATUS_LOGGEDIN, &WorldSession::HandleWhoOpcode }, - /*0x063*/ { "SMSG_WHO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x064*/ { "CMSG_WHOIS", STATUS_LOGGEDIN, &WorldSession::HandleWhoisOpcode }, - /*0x065*/ { "SMSG_WHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x066*/ { "CMSG_CONTACT_LIST", STATUS_LOGGEDIN, &WorldSession::HandleFriendListOpcode }, - /*0x067*/ { "SMSG_CONTACT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x068*/ { "SMSG_FRIEND_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x069*/ { "CMSG_ADD_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleAddFriendOpcode }, - /*0x06A*/ { "CMSG_DEL_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleDelFriendOpcode }, - /*0x06B*/ { "CMSG_SET_CONTACT_NOTES", STATUS_LOGGEDIN, &WorldSession::HandleSetFriendNoteOpcode }, - /*0x06C*/ { "CMSG_ADD_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleAddIgnoreOpcode }, - /*0x06D*/ { "CMSG_DEL_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleDelIgnoreOpcode }, - /*0x06E*/ { "CMSG_GROUP_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupInviteOpcode }, - /*0x06F*/ { "SMSG_GROUP_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x070*/ { "CMSG_GROUP_CANCEL", STATUS_LOGGEDIN, &WorldSession::Handle_Deprecated }, - /*0x071*/ { "SMSG_GROUP_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x072*/ { "CMSG_GROUP_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGroupAcceptOpcode }, - /*0x073*/ { "CMSG_GROUP_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGroupDeclineOpcode }, - /*0x074*/ { "SMSG_GROUP_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x075*/ { "CMSG_GROUP_UNINVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteNameOpcode }, - /*0x076*/ { "CMSG_GROUP_UNINVITE_GUID", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteGuidOpcode }, - /*0x077*/ { "SMSG_GROUP_UNINVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x078*/ { "CMSG_GROUP_SET_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupSetLeaderOpcode }, - /*0x079*/ { "SMSG_GROUP_SET_LEADER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07A*/ { "CMSG_LOOT_METHOD", STATUS_LOGGEDIN, &WorldSession::HandleLootMethodOpcode }, - /*0x07B*/ { "CMSG_GROUP_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGroupLeaveOpcode }, - /*0x07C*/ { "SMSG_GROUP_DESTROYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07D*/ { "SMSG_GROUP_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07E*/ { "SMSG_PARTY_MEMBER_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x07F*/ { "SMSG_PARTY_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x080*/ { "UMSG_UPDATE_GROUP_MEMBERS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x081*/ { "CMSG_GUILD_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildCreateOpcode }, - /*0x082*/ { "CMSG_GUILD_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGuildInviteOpcode }, - /*0x083*/ { "SMSG_GUILD_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x084*/ { "CMSG_GUILD_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGuildAcceptOpcode }, - /*0x085*/ { "CMSG_GUILD_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDeclineOpcode }, - /*0x086*/ { "SMSG_GUILD_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x087*/ { "CMSG_GUILD_INFO", STATUS_LOGGEDIN, &WorldSession::HandleGuildInfoOpcode }, - /*0x088*/ { "SMSG_GUILD_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x089*/ { "CMSG_GUILD_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleGuildRosterOpcode }, - /*0x08A*/ { "SMSG_GUILD_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x08B*/ { "CMSG_GUILD_PROMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildPromoteOpcode }, - /*0x08C*/ { "CMSG_GUILD_DEMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDemoteOpcode }, - /*0x08D*/ { "CMSG_GUILD_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaveOpcode }, - /*0x08E*/ { "CMSG_GUILD_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildRemoveOpcode }, - /*0x08F*/ { "CMSG_GUILD_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGuildDisbandOpcode }, - /*0x090*/ { "CMSG_GUILD_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaderOpcode }, - /*0x091*/ { "CMSG_GUILD_MOTD", STATUS_LOGGEDIN, &WorldSession::HandleGuildMOTDOpcode }, - /*0x092*/ { "SMSG_GUILD_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x093*/ { "SMSG_GUILD_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x094*/ { "UMSG_UPDATE_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x095*/ { "CMSG_MESSAGECHAT", STATUS_LOGGEDIN, &WorldSession::HandleMessagechatOpcode }, - /*0x096*/ { "SMSG_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x097*/ { "CMSG_JOIN_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoin }, - /*0x098*/ { "CMSG_LEAVE_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelLeave }, - /*0x099*/ { "SMSG_CHANNEL_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x09A*/ { "CMSG_CHANNEL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelList }, - /*0x09B*/ { "SMSG_CHANNEL_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x09C*/ { "CMSG_CHANNEL_PASSWORD", STATUS_LOGGEDIN, &WorldSession::HandleChannelPassword }, - /*0x09D*/ { "CMSG_CHANNEL_SET_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelSetOwner }, - /*0x09E*/ { "CMSG_CHANNEL_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelOwner }, - /*0x09F*/ { "CMSG_CHANNEL_MODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerator }, - /*0x0A0*/ { "CMSG_CHANNEL_UNMODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmoderator }, - /*0x0A1*/ { "CMSG_CHANNEL_MUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelMute }, - /*0x0A2*/ { "CMSG_CHANNEL_UNMUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmute }, - /*0x0A3*/ { "CMSG_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelInvite }, - /*0x0A4*/ { "CMSG_CHANNEL_KICK", STATUS_LOGGEDIN, &WorldSession::HandleChannelKick }, - /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelBan }, - /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnban }, - /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleChannelAnnounce }, - /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerate }, - /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleUseItemOpcode }, - /*0x0AC*/ { "CMSG_OPEN_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleOpenItemOpcode }, - /*0x0AD*/ { "CMSG_READ_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleReadItem }, - /*0x0AE*/ { "SMSG_READ_ITEM_OK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0AF*/ { "SMSG_READ_ITEM_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0B0*/ { "SMSG_ITEM_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0B1*/ { "CMSG_GAMEOBJ_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectUseOpcode }, - /*0x0B2*/ { "CMSG_GAMEOBJ_CHAIR_USE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0B3*/ { "SMSG_GAMEOBJECT_CUSTOM_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0B4*/ { "CMSG_AREATRIGGER", STATUS_LOGGEDIN, &WorldSession::HandleAreaTriggerOpcode }, - /*0x0B5*/ { "MSG_MOVE_START_FORWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B6*/ { "MSG_MOVE_START_BACKWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B7*/ { "MSG_MOVE_STOP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B8*/ { "MSG_MOVE_START_STRAFE_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0B9*/ { "MSG_MOVE_START_STRAFE_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BA*/ { "MSG_MOVE_STOP_STRAFE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BB*/ { "MSG_MOVE_JUMP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BC*/ { "MSG_MOVE_START_TURN_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BD*/ { "MSG_MOVE_START_TURN_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BE*/ { "MSG_MOVE_STOP_TURN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0BF*/ { "MSG_MOVE_START_PITCH_UP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C0*/ { "MSG_MOVE_START_PITCH_DOWN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C1*/ { "MSG_MOVE_STOP_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C2*/ { "MSG_MOVE_SET_RUN_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C3*/ { "MSG_MOVE_SET_WALK_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0C4*/ { "MSG_MOVE_TOGGLE_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C5*/ { "MSG_MOVE_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C6*/ { "MSG_MOVE_TELEPORT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C7*/ { "MSG_MOVE_TELEPORT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveTeleportAck }, - /*0x0C8*/ { "MSG_MOVE_TOGGLE_FALL_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0C9*/ { "MSG_MOVE_FALL_LAND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0CA*/ { "MSG_MOVE_START_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0CB*/ { "MSG_MOVE_STOP_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0CC*/ { "MSG_MOVE_SET_RUN_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0CD*/ { "MSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0CE*/ { "MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0CF*/ { "MSG_MOVE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D0*/ { "MSG_MOVE_SET_WALK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D1*/ { "MSG_MOVE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D2*/ { "MSG_MOVE_SET_SWIM_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D3*/ { "MSG_MOVE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D4*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D5*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D6*/ { "MSG_MOVE_SET_ALL_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D7*/ { "MSG_MOVE_SET_TURN_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D8*/ { "MSG_MOVE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0D9*/ { "MSG_MOVE_TOGGLE_COLLISION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0DA*/ { "MSG_MOVE_SET_FACING", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0DB*/ { "MSG_MOVE_SET_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0DC*/ { "MSG_MOVE_WORLDPORT_ACK", STATUS_TRANSFER_PENDING, &WorldSession::HandleMoveWorldportAckOpcode}, - /*0x0DD*/ { "SMSG_MONSTER_MOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0DE*/ { "SMSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0DF*/ { "SMSG_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E0*/ { "MSG_MOVE_SET_RAW_POSITION_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0E1*/ { "CMSG_MOVE_SET_RAW_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0E2*/ { "SMSG_FORCE_RUN_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E3*/ { "CMSG_FORCE_RUN_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x0E4*/ { "SMSG_FORCE_RUN_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E5*/ { "CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, - /*0x0E6*/ { "SMSG_FORCE_SWIM_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E7*/ { "CMSG_FORCE_SWIM_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x0E8*/ { "SMSG_FORCE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0E9*/ { "CMSG_FORCE_MOVE_ROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveRootAck }, - /*0x0EA*/ { "SMSG_FORCE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0EB*/ { "CMSG_FORCE_MOVE_UNROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveUnRootAck }, - /*0x0EC*/ { "MSG_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0ED*/ { "MSG_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0EE*/ { "MSG_MOVE_HEARTBEAT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x0EF*/ { "SMSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F0*/ { "CMSG_MOVE_KNOCK_BACK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveKnockBackAck }, - /*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveHoverAck }, - /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0FB*/ { "CMSG_NEXT_CINEMATIC_CAMERA", STATUS_LOGGEDIN, &WorldSession::HandleNextCinematicCamera }, - /*0x0FC*/ { "CMSG_COMPLETE_CINEMATIC", STATUS_LOGGEDIN, &WorldSession::HandleCompleteCinema }, - /*0x0FD*/ { "SMSG_TUTORIAL_FLAGS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x0FE*/ { "CMSG_TUTORIAL_FLAG", STATUS_LOGGEDIN, &WorldSession::HandleTutorialFlag }, - /*0x0FF*/ { "CMSG_TUTORIAL_CLEAR", STATUS_LOGGEDIN, &WorldSession::HandleTutorialClear }, - /*0x100*/ { "CMSG_TUTORIAL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleTutorialReset }, - /*0x101*/ { "CMSG_STANDSTATECHANGE", STATUS_LOGGEDIN, &WorldSession::HandleStandStateChangeOpcode }, - /*0x102*/ { "CMSG_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleEmoteOpcode }, - /*0x103*/ { "SMSG_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x104*/ { "CMSG_TEXT_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleTextEmoteOpcode }, - /*0x105*/ { "SMSG_TEXT_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x106*/ { "CMSG_AUTOEQUIP_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x107*/ { "CMSG_AUTOSTORE_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x108*/ { "CMSG_AUTOSTORE_LOOT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutostoreLootItemOpcode }, - /*0x109*/ { "CMSG_STORE_LOOT_IN_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x10A*/ { "CMSG_AUTOEQUIP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemOpcode }, - /*0x10B*/ { "CMSG_AUTOSTORE_BAG_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBagItemOpcode }, - /*0x10C*/ { "CMSG_SWAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapItem }, - /*0x10D*/ { "CMSG_SWAP_INV_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapInvItemOpcode }, - /*0x10E*/ { "CMSG_SPLIT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSplitItemOpcode }, - /*0x10F*/ { "CMSG_AUTOEQUIP_ITEM_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemSlotOpcode }, - /*0x110*/ { "OBSOLETE_DROP_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x111*/ { "CMSG_DESTROYITEM", STATUS_LOGGEDIN, &WorldSession::HandleDestroyItemOpcode }, - /*0x112*/ { "SMSG_INVENTORY_CHANGE_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x113*/ { "SMSG_OPEN_CONTAINER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x114*/ { "CMSG_INSPECT", STATUS_LOGGEDIN, &WorldSession::HandleInspectOpcode }, - /*0x115*/ { "SMSG_INSPECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x116*/ { "CMSG_INITIATE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleInitiateTradeOpcode }, - /*0x117*/ { "CMSG_BEGIN_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBeginTradeOpcode }, - /*0x118*/ { "CMSG_BUSY_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBusyTradeOpcode }, - /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleIgnoreTradeOpcode }, - /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleAcceptTradeOpcode }, - /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleUnacceptTradeOpcode }, - /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_AUTHED, &WorldSession::HandleCancelTradeOpcode }, - /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeItemOpcode }, - /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleClearTradeItemOpcode }, - /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeGoldOpcode }, - /*0x120*/ { "SMSG_TRADE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x121*/ { "SMSG_TRADE_STATUS_EXTENDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x122*/ { "SMSG_INITIALIZE_FACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x123*/ { "SMSG_SET_FACTION_VISIBLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x124*/ { "SMSG_SET_FACTION_STANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x125*/ { "CMSG_SET_FACTION_ATWAR", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionAtWar }, - /*0x126*/ { "CMSG_SET_FACTION_CHEAT", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionCheat }, - /*0x127*/ { "SMSG_SET_PROFICIENCY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x128*/ { "CMSG_SET_ACTION_BUTTON", STATUS_LOGGEDIN, &WorldSession::HandleSetActionButtonOpcode }, - /*0x129*/ { "SMSG_ACTION_BUTTONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12A*/ { "SMSG_INITIAL_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12B*/ { "SMSG_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12C*/ { "SMSG_SUPERCEDED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x12D*/ { "CMSG_NEW_SPELL_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x12E*/ { "CMSG_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCastSpellOpcode }, - /*0x12F*/ { "CMSG_CANCEL_CAST", STATUS_LOGGEDIN, &WorldSession::HandleCancelCastOpcode }, - /*0x130*/ { "SMSG_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x131*/ { "SMSG_SPELL_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x132*/ { "SMSG_SPELL_GO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x133*/ { "SMSG_SPELL_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x134*/ { "SMSG_SPELL_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x135*/ { "SMSG_COOLDOWN_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x136*/ { "CMSG_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelAuraOpcode }, - /*0x137*/ { "SMSG_UPDATE_AURA_DURATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x138*/ { "SMSG_PET_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x139*/ { "MSG_CHANNEL_START", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x13A*/ { "MSG_CHANNEL_UPDATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x13B*/ { "CMSG_CANCEL_CHANNELLING", STATUS_LOGGEDIN, &WorldSession::HandleCancelChanneling }, - /*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, &WorldSession::HandleSetSelectionOpcode }, - /*0x13E*/ { "CMSG_SET_TARGET_OBSOLETE", STATUS_LOGGEDIN, &WorldSession::HandleSetTargetOpcode }, - /*0x13F*/ { "CMSG_UNUSED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x140*/ { "CMSG_UNUSED2", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, &WorldSession::HandleAttackSwingOpcode }, - /*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, &WorldSession::HandleAttackStopOpcode }, - /*0x143*/ { "SMSG_ATTACKSTART", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x147*/ { "SMSG_ATTACKSWING_NOTSTANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14B*/ { "SMSG_VICTIMSTATEUPDATE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14C*/ { "SMSG_DAMAGE_DONE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14D*/ { "SMSG_DAMAGE_TAKEN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x14F*/ { "SMSG_PLAYER_COMBAT_XP_GAIN_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x151*/ { "SMSG_SPELLENERGIZELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x152*/ { "CMSG_SHEATHE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x153*/ { "CMSG_SAVE_PLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x154*/ { "CMSG_SETDEATHBINDPOINT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x155*/ { "SMSG_BINDPOINTUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x156*/ { "CMSG_GETDEATHBINDZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x157*/ { "SMSG_BINDZONEREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x158*/ { "SMSG_PLAYERBOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x159*/ { "SMSG_CLIENT_CONTROL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x15A*/ { "CMSG_REPOP_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleRepopRequestOpcode }, - /*0x15B*/ { "SMSG_RESURRECT_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x15C*/ { "CMSG_RESURRECT_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleResurrectResponseOpcode }, - /*0x15D*/ { "CMSG_LOOT", STATUS_LOGGEDIN, &WorldSession::HandleLootOpcode }, - /*0x15E*/ { "CMSG_LOOT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleLootMoneyOpcode }, - /*0x15F*/ { "CMSG_LOOT_RELEASE", STATUS_LOGGEDIN, &WorldSession::HandleLootReleaseOpcode }, - /*0x160*/ { "SMSG_LOOT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x161*/ { "SMSG_LOOT_RELEASE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x162*/ { "SMSG_LOOT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x163*/ { "SMSG_LOOT_MONEY_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x164*/ { "SMSG_LOOT_ITEM_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x165*/ { "SMSG_LOOT_CLEAR_MONEY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x166*/ { "SMSG_ITEM_PUSH_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x167*/ { "SMSG_DUEL_REQUESTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x168*/ { "SMSG_DUEL_OUTOFBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x169*/ { "SMSG_DUEL_INBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16A*/ { "SMSG_DUEL_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16B*/ { "SMSG_DUEL_WINNER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16C*/ { "CMSG_DUEL_ACCEPTED", STATUS_LOGGEDIN, &WorldSession::HandleDuelAcceptedOpcode }, - /*0x16D*/ { "CMSG_DUEL_CANCELLED", STATUS_LOGGEDIN, &WorldSession::HandleDuelCancelledOpcode }, - /*0x16E*/ { "SMSG_MOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x16F*/ { "SMSG_DISMOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x170*/ { "SMSG_PUREMOUNT_CANCELLED_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x171*/ { "CMSG_MOUNTSPECIAL_ANIM", STATUS_LOGGEDIN, &WorldSession::HandleMountSpecialAnimOpcode }, - /*0x172*/ { "SMSG_MOUNTSPECIAL_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x173*/ { "SMSG_PET_TAME_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x174*/ { "CMSG_PET_SET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetSetAction }, - /*0x175*/ { "CMSG_PET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetAction }, - /*0x176*/ { "CMSG_PET_ABANDON", STATUS_LOGGEDIN, &WorldSession::HandlePetAbandon }, - /*0x177*/ { "CMSG_PET_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetRename }, - /*0x178*/ { "SMSG_PET_NAME_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x179*/ { "SMSG_PET_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17A*/ { "SMSG_PET_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17B*/ { "CMSG_GOSSIP_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleGossipHelloOpcode }, - /*0x17C*/ { "CMSG_GOSSIP_SELECT_OPTION", STATUS_LOGGEDIN, &WorldSession::HandleGossipSelectOptionOpcode }, - /*0x17D*/ { "SMSG_GOSSIP_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17E*/ { "SMSG_GOSSIP_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x17F*/ { "CMSG_NPC_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNpcTextQueryOpcode }, - /*0x180*/ { "SMSG_NPC_TEXT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x181*/ { "SMSG_NPC_WONT_TALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x182*/ { "CMSG_QUESTGIVER_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryOpcode}, - /*0x183*/ { "SMSG_QUESTGIVER_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x184*/ { "CMSG_QUESTGIVER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverHelloOpcode }, - /*0x185*/ { "SMSG_QUESTGIVER_QUEST_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x186*/ { "CMSG_QUESTGIVER_QUERY_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverQuestQueryOpcode}, - /*0x187*/ { "CMSG_QUESTGIVER_QUEST_AUTOLAUNCH", STATUS_LOGGEDIN, &WorldSession::HandleQuestAutoLaunch }, - /*0x188*/ { "SMSG_QUESTGIVER_QUEST_DETAILS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x189*/ { "CMSG_QUESTGIVER_ACCEPT_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverAcceptQuestOpcode}, - /*0x18A*/ { "CMSG_QUESTGIVER_COMPLETE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestComplete }, - /*0x18B*/ { "SMSG_QUESTGIVER_REQUEST_ITEMS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x18C*/ { "CMSG_QUESTGIVER_REQUEST_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverRequestRewardOpcode}, - /*0x18D*/ { "SMSG_QUESTGIVER_OFFER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x18E*/ { "CMSG_QUESTGIVER_CHOOSE_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverChooseRewardOpcode}, - /*0x18F*/ { "SMSG_QUESTGIVER_QUEST_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x190*/ { "CMSG_QUESTGIVER_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverCancel }, - /*0x191*/ { "SMSG_QUESTGIVER_QUEST_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x192*/ { "SMSG_QUESTGIVER_QUEST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x193*/ { "CMSG_QUESTLOG_SWAP_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogSwapQuest }, - /*0x194*/ { "CMSG_QUESTLOG_REMOVE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogRemoveQuest }, - /*0x195*/ { "SMSG_QUESTLOG_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x196*/ { "SMSG_QUESTUPDATE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x197*/ { "SMSG_QUESTUPDATE_FAILEDTIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x198*/ { "SMSG_QUESTUPDATE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x199*/ { "SMSG_QUESTUPDATE_ADD_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x19A*/ { "SMSG_QUESTUPDATE_ADD_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x19B*/ { "CMSG_QUEST_CONFIRM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleQuestConfirmAccept }, - /*0x19C*/ { "SMSG_QUEST_CONFIRM_ACCEPT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x19D*/ { "CMSG_PUSHQUESTTOPARTY", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushToParty }, - /*0x19E*/ { "CMSG_LIST_INVENTORY", STATUS_LOGGEDIN, &WorldSession::HandleListInventoryOpcode }, - /*0x19F*/ { "SMSG_LIST_INVENTORY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A0*/ { "CMSG_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSellItemOpcode }, - /*0x1A1*/ { "SMSG_SELL_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A2*/ { "CMSG_BUY_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemOpcode }, - /*0x1A3*/ { "CMSG_BUY_ITEM_IN_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemInSlotOpcode }, - /*0x1A4*/ { "SMSG_BUY_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A5*/ { "SMSG_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1A6*/ { "CMSG_TAXICLEARALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1A7*/ { "CMSG_TAXIENABLEALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1A8*/ { "CMSG_TAXISHOWNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1A9*/ { "SMSG_SHOWTAXINODES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1AA*/ { "CMSG_TAXINODE_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNodeStatusQueryOpcode }, - /*0x1AB*/ { "SMSG_TAXINODE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1AC*/ { "CMSG_TAXIQUERYAVAILABLENODES", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodesOpcode}, - /*0x1AD*/ { "CMSG_ACTIVATETAXI", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiOpcode }, - /*0x1AE*/ { "SMSG_ACTIVATETAXIREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1AF*/ { "SMSG_NEW_TAXI_PATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B0*/ { "CMSG_TRAINER_LIST", STATUS_LOGGEDIN, &WorldSession::HandleTrainerListOpcode }, - /*0x1B1*/ { "SMSG_TRAINER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B2*/ { "CMSG_TRAINER_BUY_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleTrainerBuySpellOpcode }, - /*0x1B3*/ { "SMSG_TRAINER_BUY_SUCCEEDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B4*/ { "SMSG_TRAINER_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B5*/ { "CMSG_BINDER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBinderActivateOpcode }, - /*0x1B6*/ { "SMSG_PLAYERBINDERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B7*/ { "CMSG_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBankerActivateOpcode }, - /*0x1B8*/ { "SMSG_SHOW_BANK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1B9*/ { "CMSG_BUY_BANK_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyBankSlotOpcode }, - /*0x1BA*/ { "SMSG_BUY_BANK_SLOT_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1BB*/ { "CMSG_PETITION_SHOWLIST", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowListOpcode }, - /*0x1BC*/ { "SMSG_PETITION_SHOWLIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1BD*/ { "CMSG_PETITION_BUY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionBuyOpcode }, - /*0x1BE*/ { "CMSG_PETITION_SHOW_SIGNATURES", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowSignOpcode }, - /*0x1BF*/ { "SMSG_PETITION_SHOW_SIGNATURES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C0*/ { "CMSG_PETITION_SIGN", STATUS_LOGGEDIN, &WorldSession::HandlePetitionSignOpcode }, - /*0x1C1*/ { "SMSG_PETITION_SIGN_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C2*/ { "MSG_PETITION_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandlePetitionDeclineOpcode }, - /*0x1C3*/ { "CMSG_OFFER_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleOfferPetitionOpcode }, - /*0x1C4*/ { "CMSG_TURN_IN_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleTurnInPetitionOpcode }, - /*0x1C5*/ { "SMSG_TURN_IN_PETITION_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C6*/ { "CMSG_PETITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionQueryOpcode }, - /*0x1C7*/ { "SMSG_PETITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C8*/ { "SMSG_FISH_NOT_HOOKED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1C9*/ { "SMSG_FISH_ESCAPED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1CA*/ { "CMSG_BUG", STATUS_LOGGEDIN, &WorldSession::HandleBugOpcode }, - /*0x1CB*/ { "SMSG_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1CC*/ { "CMSG_PLAYED_TIME", STATUS_LOGGEDIN, &WorldSession::HandlePlayedTime }, - /*0x1CD*/ { "SMSG_PLAYED_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1CE*/ { "CMSG_QUERY_TIME", STATUS_LOGGEDIN, &WorldSession::HandleQueryTimeOpcode }, - /*0x1CF*/ { "SMSG_QUERY_TIME_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D0*/ { "SMSG_LOG_XPGAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D1*/ { "SMSG_AURACASTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D2*/ { "CMSG_RECLAIM_CORPSE", STATUS_LOGGEDIN, &WorldSession::HandleCorpseReclaimOpcode }, - /*0x1D3*/ { "CMSG_WRAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleWrapItemOpcode }, - /*0x1D4*/ { "SMSG_LEVELUP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D5*/ { "MSG_MINIMAP_PING", STATUS_LOGGEDIN, &WorldSession::HandleMinimapPingOpcode }, - /*0x1D6*/ { "SMSG_RESISTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D7*/ { "SMSG_ENCHANTMENTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1D8*/ { "CMSG_SET_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1D9*/ { "SMSG_START_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DA*/ { "SMSG_PAUSE_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DB*/ { "SMSG_STOP_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DC*/ { "CMSG_PING", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, - /*0x1DD*/ { "SMSG_PONG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DE*/ { "SMSG_CLEAR_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1DF*/ { "SMSG_GAMEOBJECT_PAGETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E0*/ { "CMSG_SETSHEATHED", STATUS_LOGGEDIN, &WorldSession::HandleSetSheathedOpcode }, - /*0x1E1*/ { "SMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E2*/ { "SMSG_SPELL_DELAYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E3*/ { "CMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1E4*/ { "SMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E5*/ { "CMSG_GHOST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1E6*/ { "CMSG_GM_INVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1E7*/ { "SMSG_INVALID_PROMOTION_CODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1E8*/ { "MSG_GM_BIND_OTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1E9*/ { "MSG_GM_SUMMON", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1EA*/ { "SMSG_ITEM_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1EB*/ { "SMSG_ITEM_ENCHANT_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1EC*/ { "SMSG_AUTH_CHALLENGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1ED*/ { "CMSG_AUTH_SESSION", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, - /*0x1EE*/ { "SMSG_AUTH_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1EF*/ { "MSG_GM_SHOWLABEL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1F0*/ { "CMSG_PET_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandlePetCastSpellOpcode }, - /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, &WorldSession::HandleGuildSaveEmblemOpcode }, - /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleTabardVendorActivateOpcode}, - /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, &WorldSession::HandleZoneUpdateOpcode }, - /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F8*/ { "SMSG_EXPLORATION_EXPERIENCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1F9*/ { "CMSG_GM_SET_SECURITY_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1FA*/ { "CMSG_GM_NUKE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1FB*/ { "MSG_RANDOM_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleRandomRollOpcode }, - /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1FD*/ { "CMSG_RWHOIS_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x1FF*/ { "MSG_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLookingForGroup }, - /*0x200*/ { "CMSG_SET_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleSetLfgOpcode }, - /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, &WorldSession::HandleUnlearnSkillOpcode }, - /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketCreateOpcode }, - /*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x000*/ { "MSG_NULL_ACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x001*/ { "CMSG_BOOTME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x002*/ { "CMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x003*/ { "SMSG_DBLOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x004*/ { "CMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x005*/ { "SMSG_QUERY_OBJECT_POSITION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x006*/ { "CMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x007*/ { "SMSG_QUERY_OBJECT_ROTATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x008*/ { "CMSG_WORLD_TELEPORT", STATUS_LOGGEDIN, &WorldSession::HandleWorldTeleportOpcode }, + /*0x009*/ { "CMSG_TELEPORT_TO_UNIT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL }, + /*0x00A*/ { "CMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00B*/ { "SMSG_ZONE_MAP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x00C*/ { "CMSG_DEBUG_CHANGECELLZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00D*/ { "CMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00E*/ { "SMSG_MOVE_CHARACTER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x00F*/ { "CMSG_RECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x010*/ { "CMSG_LEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x011*/ { "CMSG_CREATEMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x012*/ { "CMSG_DESTROYMONSTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x013*/ { "CMSG_CREATEITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x014*/ { "CMSG_CREATEGAMEOBJECT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x015*/ { "SMSG_CHECK_FOR_BOTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x016*/ { "CMSG_MAKEMONSTERATTACKGUID", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x017*/ { "CMSG_BOT_DETECTED2", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x018*/ { "CMSG_FORCEACTION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x019*/ { "CMSG_FORCEACTIONONOTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01A*/ { "CMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01B*/ { "SMSG_FORCEACTIONSHOW", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01C*/ { "CMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x01D*/ { "SMSG_PETGODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01E*/ { "SMSG_REFER_A_FRIEND_EXPIRED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x01F*/ { "CMSG_WEATHER_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x020*/ { "CMSG_UNDRESSPLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x021*/ { "CMSG_BEASTMASTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x022*/ { "CMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x023*/ { "SMSG_GODMODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x024*/ { "CMSG_CHEAT_SETMONEY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x025*/ { "CMSG_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x026*/ { "CMSG_PET_LEVEL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x027*/ { "CMSG_SET_WORLDSTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x028*/ { "CMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x029*/ { "CMSG_USE_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02A*/ { "CMSG_FLAG_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02B*/ { "CMSG_FLAG_QUEST_FINISH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02C*/ { "CMSG_CLEAR_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02D*/ { "CMSG_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02E*/ { "CMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x02F*/ { "SMSG_DEBUG_AISTATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x030*/ { "CMSG_DISABLE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x031*/ { "CMSG_ADVANCE_SPAWN_TIME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x032*/ { "SMSG_DESTRUCTIBLE_BUILDING_DAMAGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x033*/ { "CMSG_AUTH_SRP6_BEGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x034*/ { "CMSG_AUTH_SRP6_PROOF", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x035*/ { "CMSG_AUTH_SRP6_RECODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x036*/ { "CMSG_CHAR_CREATE", STATUS_AUTHED, &WorldSession::HandleCharCreateOpcode }, + /*0x037*/ { "CMSG_CHAR_ENUM", STATUS_AUTHED, &WorldSession::HandleCharEnumOpcode }, + /*0x038*/ { "CMSG_CHAR_DELETE", STATUS_AUTHED, &WorldSession::HandleCharDeleteOpcode }, + /*0x039*/ { "SMSG_AUTH_SRP6_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03A*/ { "SMSG_CHAR_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03B*/ { "SMSG_CHAR_ENUM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03C*/ { "SMSG_CHAR_DELETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03D*/ { "CMSG_PLAYER_LOGIN", STATUS_AUTHED, &WorldSession::HandlePlayerLoginOpcode }, + /*0x03E*/ { "SMSG_NEW_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x03F*/ { "SMSG_TRANSFER_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x040*/ { "SMSG_TRANSFER_ABORTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x041*/ { "SMSG_CHARACTER_LOGIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x042*/ { "SMSG_LOGIN_SETTIMESPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x043*/ { "SMSG_GAMETIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x044*/ { "CMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x045*/ { "SMSG_GAMETIME_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x046*/ { "CMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x047*/ { "SMSG_GAMESPEED_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x048*/ { "CMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x049*/ { "SMSG_SERVERTIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04A*/ { "CMSG_PLAYER_LOGOUT", STATUS_LOGGEDIN, &WorldSession::HandlePlayerLogoutOpcode }, + /*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleLogoutRequestOpcode }, + /*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleLogoutCancelOpcode }, + /*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNameQueryOpcode }, + /*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x052*/ { "CMSG_PET_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetNameQuery }, + /*0x053*/ { "SMSG_PET_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x054*/ { "CMSG_GUILD_QUERY", STATUS_AUTHED, &WorldSession::HandleGuildQueryOpcode }, + /*0x055*/ { "SMSG_GUILD_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x056*/ { "CMSG_ITEM_QUERY_SINGLE", STATUS_LOGGEDIN, &WorldSession::HandleItemQuerySingleOpcode }, + /*0x057*/ { "CMSG_ITEM_QUERY_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x058*/ { "SMSG_ITEM_QUERY_SINGLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x059*/ { "SMSG_ITEM_QUERY_MULTIPLE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05A*/ { "CMSG_PAGE_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePageQueryOpcode }, + /*0x05B*/ { "SMSG_PAGE_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05C*/ { "CMSG_QUEST_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestQueryOpcode }, + /*0x05D*/ { "SMSG_QUEST_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x05E*/ { "CMSG_GAMEOBJECT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectQueryOpcode }, + /*0x05F*/ { "SMSG_GAMEOBJECT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x060*/ { "CMSG_CREATURE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCreatureQueryOpcode }, + /*0x061*/ { "SMSG_CREATURE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x062*/ { "CMSG_WHO", STATUS_LOGGEDIN, &WorldSession::HandleWhoOpcode }, + /*0x063*/ { "SMSG_WHO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x064*/ { "CMSG_WHOIS", STATUS_LOGGEDIN, &WorldSession::HandleWhoisOpcode }, + /*0x065*/ { "SMSG_WHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x066*/ { "CMSG_CONTACT_LIST", STATUS_LOGGEDIN, &WorldSession::HandleFriendListOpcode }, + /*0x067*/ { "SMSG_CONTACT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x068*/ { "SMSG_FRIEND_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x069*/ { "CMSG_ADD_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleAddFriendOpcode }, + /*0x06A*/ { "CMSG_DEL_FRIEND", STATUS_LOGGEDIN, &WorldSession::HandleDelFriendOpcode }, + /*0x06B*/ { "CMSG_SET_CONTACT_NOTES", STATUS_LOGGEDIN, &WorldSession::HandleSetFriendNoteOpcode }, + /*0x06C*/ { "CMSG_ADD_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleAddIgnoreOpcode }, + /*0x06D*/ { "CMSG_DEL_IGNORE", STATUS_LOGGEDIN, &WorldSession::HandleDelIgnoreOpcode }, + /*0x06E*/ { "CMSG_GROUP_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupInviteOpcode }, + /*0x06F*/ { "SMSG_GROUP_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x070*/ { "CMSG_GROUP_CANCEL", STATUS_LOGGEDIN, &WorldSession::Handle_Deprecated }, + /*0x071*/ { "SMSG_GROUP_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x072*/ { "CMSG_GROUP_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGroupAcceptOpcode }, + /*0x073*/ { "CMSG_GROUP_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGroupDeclineOpcode }, + /*0x074*/ { "SMSG_GROUP_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x075*/ { "CMSG_GROUP_UNINVITE", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteNameOpcode }, + /*0x076*/ { "CMSG_GROUP_UNINVITE_GUID", STATUS_LOGGEDIN, &WorldSession::HandleGroupUninviteGuidOpcode }, + /*0x077*/ { "SMSG_GROUP_UNINVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x078*/ { "CMSG_GROUP_SET_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupSetLeaderOpcode }, + /*0x079*/ { "SMSG_GROUP_SET_LEADER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07A*/ { "CMSG_LOOT_METHOD", STATUS_LOGGEDIN, &WorldSession::HandleLootMethodOpcode }, + /*0x07B*/ { "CMSG_GROUP_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGroupLeaveOpcode }, + /*0x07C*/ { "SMSG_GROUP_DESTROYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07D*/ { "SMSG_GROUP_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07E*/ { "SMSG_PARTY_MEMBER_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x07F*/ { "SMSG_PARTY_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x080*/ { "UMSG_UPDATE_GROUP_MEMBERS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x081*/ { "CMSG_GUILD_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildCreateOpcode }, + /*0x082*/ { "CMSG_GUILD_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleGuildInviteOpcode }, + /*0x083*/ { "SMSG_GUILD_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x084*/ { "CMSG_GUILD_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleGuildAcceptOpcode }, + /*0x085*/ { "CMSG_GUILD_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDeclineOpcode }, + /*0x086*/ { "SMSG_GUILD_DECLINE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x087*/ { "CMSG_GUILD_INFO", STATUS_LOGGEDIN, &WorldSession::HandleGuildInfoOpcode }, + /*0x088*/ { "SMSG_GUILD_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x089*/ { "CMSG_GUILD_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleGuildRosterOpcode }, + /*0x08A*/ { "SMSG_GUILD_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x08B*/ { "CMSG_GUILD_PROMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildPromoteOpcode }, + /*0x08C*/ { "CMSG_GUILD_DEMOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildDemoteOpcode }, + /*0x08D*/ { "CMSG_GUILD_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaveOpcode }, + /*0x08E*/ { "CMSG_GUILD_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleGuildRemoveOpcode }, + /*0x08F*/ { "CMSG_GUILD_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleGuildDisbandOpcode }, + /*0x090*/ { "CMSG_GUILD_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGuildLeaderOpcode }, + /*0x091*/ { "CMSG_GUILD_MOTD", STATUS_LOGGEDIN, &WorldSession::HandleGuildMOTDOpcode }, + /*0x092*/ { "SMSG_GUILD_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x093*/ { "SMSG_GUILD_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x094*/ { "UMSG_UPDATE_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x095*/ { "CMSG_MESSAGECHAT", STATUS_LOGGEDIN, &WorldSession::HandleMessagechatOpcode }, + /*0x096*/ { "SMSG_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x097*/ { "CMSG_JOIN_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoin }, + /*0x098*/ { "CMSG_LEAVE_CHANNEL", STATUS_LOGGEDIN, &WorldSession::HandleChannelLeave }, + /*0x099*/ { "SMSG_CHANNEL_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x09A*/ { "CMSG_CHANNEL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelList }, + /*0x09B*/ { "SMSG_CHANNEL_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x09C*/ { "CMSG_CHANNEL_PASSWORD", STATUS_LOGGEDIN, &WorldSession::HandleChannelPassword }, + /*0x09D*/ { "CMSG_CHANNEL_SET_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelSetOwner }, + /*0x09E*/ { "CMSG_CHANNEL_OWNER", STATUS_LOGGEDIN, &WorldSession::HandleChannelOwner }, + /*0x09F*/ { "CMSG_CHANNEL_MODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerator }, + /*0x0A0*/ { "CMSG_CHANNEL_UNMODERATOR", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmoderator }, + /*0x0A1*/ { "CMSG_CHANNEL_MUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelMute }, + /*0x0A2*/ { "CMSG_CHANNEL_UNMUTE", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnmute }, + /*0x0A3*/ { "CMSG_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelInvite }, + /*0x0A4*/ { "CMSG_CHANNEL_KICK", STATUS_LOGGEDIN, &WorldSession::HandleChannelKick }, + /*0x0A5*/ { "CMSG_CHANNEL_BAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelBan }, + /*0x0A6*/ { "CMSG_CHANNEL_UNBAN", STATUS_LOGGEDIN, &WorldSession::HandleChannelUnban }, + /*0x0A7*/ { "CMSG_CHANNEL_ANNOUNCEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleChannelAnnounce }, + /*0x0A8*/ { "CMSG_CHANNEL_MODERATE", STATUS_LOGGEDIN, &WorldSession::HandleChannelModerate }, + /*0x0A9*/ { "SMSG_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AA*/ { "SMSG_DESTROY_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AB*/ { "CMSG_USE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleUseItemOpcode }, + /*0x0AC*/ { "CMSG_OPEN_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleOpenItemOpcode }, + /*0x0AD*/ { "CMSG_READ_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleReadItem }, + /*0x0AE*/ { "SMSG_READ_ITEM_OK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0AF*/ { "SMSG_READ_ITEM_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B0*/ { "SMSG_ITEM_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B1*/ { "CMSG_GAMEOBJ_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameObjectUseOpcode }, + /*0x0B2*/ { "CMSG_DESTROY_ITEMS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0B3*/ { "SMSG_GAMEOBJECT_CUSTOM_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0B4*/ { "CMSG_AREATRIGGER", STATUS_LOGGEDIN, &WorldSession::HandleAreaTriggerOpcode }, + /*0x0B5*/ { "MSG_MOVE_START_FORWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B6*/ { "MSG_MOVE_START_BACKWARD", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B7*/ { "MSG_MOVE_STOP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B8*/ { "MSG_MOVE_START_STRAFE_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0B9*/ { "MSG_MOVE_START_STRAFE_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BA*/ { "MSG_MOVE_STOP_STRAFE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BB*/ { "MSG_MOVE_JUMP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BC*/ { "MSG_MOVE_START_TURN_LEFT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BD*/ { "MSG_MOVE_START_TURN_RIGHT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BE*/ { "MSG_MOVE_STOP_TURN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0BF*/ { "MSG_MOVE_START_PITCH_UP", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C0*/ { "MSG_MOVE_START_PITCH_DOWN", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C1*/ { "MSG_MOVE_STOP_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C2*/ { "MSG_MOVE_SET_RUN_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C3*/ { "MSG_MOVE_SET_WALK_MODE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0C4*/ { "MSG_MOVE_TOGGLE_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C5*/ { "MSG_MOVE_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C6*/ { "MSG_MOVE_TELEPORT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C7*/ { "MSG_MOVE_TELEPORT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveTeleportAck }, + /*0x0C8*/ { "MSG_MOVE_TOGGLE_FALL_LOGGING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0C9*/ { "MSG_MOVE_FALL_LAND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CA*/ { "MSG_MOVE_START_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CB*/ { "MSG_MOVE_STOP_SWIM", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0CC*/ { "MSG_MOVE_SET_RUN_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CD*/ { "MSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CE*/ { "MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0CF*/ { "MSG_MOVE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D0*/ { "MSG_MOVE_SET_WALK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D1*/ { "MSG_MOVE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D2*/ { "MSG_MOVE_SET_SWIM_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D3*/ { "MSG_MOVE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D4*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D5*/ { "MSG_MOVE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D6*/ { "MSG_MOVE_SET_ALL_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D7*/ { "MSG_MOVE_SET_TURN_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D8*/ { "MSG_MOVE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0D9*/ { "MSG_MOVE_TOGGLE_COLLISION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0DA*/ { "MSG_MOVE_SET_FACING", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0DB*/ { "MSG_MOVE_SET_PITCH", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0DC*/ { "MSG_MOVE_WORLDPORT_ACK", STATUS_TRANSFER_PENDING,&WorldSession::HandleMoveWorldportAckOpcode}, + /*0x0DD*/ { "SMSG_MONSTER_MOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0DE*/ { "SMSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0DF*/ { "SMSG_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E0*/ { "MSG_MOVE_SET_RAW_POSITION_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0E1*/ { "CMSG_MOVE_SET_RAW_POSITION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0E2*/ { "SMSG_FORCE_RUN_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E3*/ { "CMSG_FORCE_RUN_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x0E4*/ { "SMSG_FORCE_RUN_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E5*/ { "CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x0E6*/ { "SMSG_FORCE_SWIM_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E7*/ { "CMSG_FORCE_SWIM_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x0E8*/ { "SMSG_FORCE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0E9*/ { "CMSG_FORCE_MOVE_ROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveRootAck }, + /*0x0EA*/ { "SMSG_FORCE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0EB*/ { "CMSG_FORCE_MOVE_UNROOT_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveUnRootAck }, + /*0x0EC*/ { "MSG_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0ED*/ { "MSG_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0EE*/ { "MSG_MOVE_HEARTBEAT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x0EF*/ { "SMSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F0*/ { "CMSG_MOVE_KNOCK_BACK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveKnockBackAck }, + /*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveHoverAck }, + /*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0F9*/ { "CMSG_OPENING_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x0FA*/ { "SMSG_TRIGGER_CINEMATIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0FB*/ { "CMSG_NEXT_CINEMATIC_CAMERA", STATUS_LOGGEDIN, &WorldSession::HandleNextCinematicCamera }, + /*0x0FC*/ { "CMSG_COMPLETE_CINEMATIC", STATUS_LOGGEDIN, &WorldSession::HandleCompleteCinema }, + /*0x0FD*/ { "SMSG_TUTORIAL_FLAGS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x0FE*/ { "CMSG_TUTORIAL_FLAG", STATUS_LOGGEDIN, &WorldSession::HandleTutorialFlag }, + /*0x0FF*/ { "CMSG_TUTORIAL_CLEAR", STATUS_LOGGEDIN, &WorldSession::HandleTutorialClear }, + /*0x100*/ { "CMSG_TUTORIAL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleTutorialReset }, + /*0x101*/ { "CMSG_STANDSTATECHANGE", STATUS_LOGGEDIN, &WorldSession::HandleStandStateChangeOpcode }, + /*0x102*/ { "CMSG_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleEmoteOpcode }, + /*0x103*/ { "SMSG_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x104*/ { "CMSG_TEXT_EMOTE", STATUS_LOGGEDIN, &WorldSession::HandleTextEmoteOpcode }, + /*0x105*/ { "SMSG_TEXT_EMOTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x106*/ { "CMSG_AUTOEQUIP_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x107*/ { "CMSG_AUTOSTORE_GROUND_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x108*/ { "CMSG_AUTOSTORE_LOOT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutostoreLootItemOpcode }, + /*0x109*/ { "CMSG_STORE_LOOT_IN_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x10A*/ { "CMSG_AUTOEQUIP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemOpcode }, + /*0x10B*/ { "CMSG_AUTOSTORE_BAG_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBagItemOpcode }, + /*0x10C*/ { "CMSG_SWAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapItem }, + /*0x10D*/ { "CMSG_SWAP_INV_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSwapInvItemOpcode }, + /*0x10E*/ { "CMSG_SPLIT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSplitItemOpcode }, + /*0x10F*/ { "CMSG_AUTOEQUIP_ITEM_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleAutoEquipItemSlotOpcode }, + /*0x110*/ { "OBSOLETE_DROP_ITEM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x111*/ { "CMSG_DESTROYITEM", STATUS_LOGGEDIN, &WorldSession::HandleDestroyItemOpcode }, + /*0x112*/ { "SMSG_INVENTORY_CHANGE_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x113*/ { "SMSG_OPEN_CONTAINER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x114*/ { "CMSG_INSPECT", STATUS_LOGGEDIN, &WorldSession::HandleInspectOpcode }, + /*0x115*/ { "SMSG_INSPECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x116*/ { "CMSG_INITIATE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleInitiateTradeOpcode }, + /*0x117*/ { "CMSG_BEGIN_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBeginTradeOpcode }, + /*0x118*/ { "CMSG_BUSY_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleBusyTradeOpcode }, + /*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleIgnoreTradeOpcode }, + /*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleAcceptTradeOpcode }, + /*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, &WorldSession::HandleUnacceptTradeOpcode }, + /*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_AUTHED, &WorldSession::HandleCancelTradeOpcode }, + /*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeItemOpcode }, + /*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleClearTradeItemOpcode }, + /*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, &WorldSession::HandleSetTradeGoldOpcode }, + /*0x120*/ { "SMSG_TRADE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x121*/ { "SMSG_TRADE_STATUS_EXTENDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x122*/ { "SMSG_INITIALIZE_FACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x123*/ { "SMSG_SET_FACTION_VISIBLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x124*/ { "SMSG_SET_FACTION_STANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x125*/ { "CMSG_SET_FACTION_ATWAR", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionAtWar }, + /*0x126*/ { "CMSG_SET_FACTION_CHEAT", STATUS_LOGGEDIN, &WorldSession::HandleSetFactionCheat }, + /*0x127*/ { "SMSG_SET_PROFICIENCY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x128*/ { "CMSG_SET_ACTION_BUTTON", STATUS_LOGGEDIN, &WorldSession::HandleSetActionButtonOpcode }, + /*0x129*/ { "SMSG_ACTION_BUTTONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12A*/ { "SMSG_INITIAL_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12B*/ { "SMSG_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12C*/ { "SMSG_SUPERCEDED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x12D*/ { "CMSG_NEW_SPELL_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x12E*/ { "CMSG_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCastSpellOpcode }, + /*0x12F*/ { "CMSG_CANCEL_CAST", STATUS_LOGGEDIN, &WorldSession::HandleCancelCastOpcode }, + /*0x130*/ { "SMSG_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x131*/ { "SMSG_SPELL_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x132*/ { "SMSG_SPELL_GO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x133*/ { "SMSG_SPELL_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x134*/ { "SMSG_SPELL_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x135*/ { "SMSG_COOLDOWN_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x136*/ { "CMSG_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelAuraOpcode }, + /*0x137*/ { "SMSG_UPDATE_AURA_DURATION_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x138*/ { "SMSG_PET_CAST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x139*/ { "MSG_CHANNEL_START", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x13A*/ { "MSG_CHANNEL_UPDATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x13B*/ { "CMSG_CANCEL_CHANNELLING", STATUS_LOGGEDIN, &WorldSession::HandleCancelChanneling }, + /*0x13C*/ { "SMSG_AI_REACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x13D*/ { "CMSG_SET_SELECTION", STATUS_LOGGEDIN, &WorldSession::HandleSetSelectionOpcode }, + /*0x13E*/ { "CMSG_SET_TARGET_OBSOLETE", STATUS_LOGGEDIN, &WorldSession::HandleSetTargetOpcode }, + /*0x13F*/ { "CMSG_UNUSED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x140*/ { "CMSG_UNUSED2", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x141*/ { "CMSG_ATTACKSWING", STATUS_LOGGEDIN, &WorldSession::HandleAttackSwingOpcode }, + /*0x142*/ { "CMSG_ATTACKSTOP", STATUS_LOGGEDIN, &WorldSession::HandleAttackStopOpcode }, + /*0x143*/ { "SMSG_ATTACKSTART", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x144*/ { "SMSG_ATTACKSTOP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x145*/ { "SMSG_ATTACKSWING_NOTINRANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x146*/ { "SMSG_ATTACKSWING_BADFACING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x147*/ { "SMSG_ATTACKSWING_NOTSTANDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x148*/ { "SMSG_ATTACKSWING_DEADTARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x149*/ { "SMSG_ATTACKSWING_CANT_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14A*/ { "SMSG_ATTACKERSTATEUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14B*/ { "SMSG_VICTIMSTATEUPDATE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14C*/ { "SMSG_DAMAGE_DONE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14D*/ { "SMSG_DAMAGE_TAKEN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14E*/ { "SMSG_CANCEL_COMBAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x14F*/ { "SMSG_SPELLBREAKLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x150*/ { "SMSG_SPELLHEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x151*/ { "SMSG_SPELLENERGIZELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x152*/ { "SMSG_BREAK_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x153*/ { "CMSG_SAVE_PLAYER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x154*/ { "CMSG_SETDEATHBINDPOINT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x155*/ { "SMSG_BINDPOINTUPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x156*/ { "CMSG_GETDEATHBINDZONE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x157*/ { "SMSG_BINDZONEREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x158*/ { "SMSG_PLAYERBOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x159*/ { "SMSG_CLIENT_CONTROL_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x15A*/ { "CMSG_REPOP_REQUEST", STATUS_LOGGEDIN, &WorldSession::HandleRepopRequestOpcode }, + /*0x15B*/ { "SMSG_RESURRECT_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x15C*/ { "CMSG_RESURRECT_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleResurrectResponseOpcode }, + /*0x15D*/ { "CMSG_LOOT", STATUS_LOGGEDIN, &WorldSession::HandleLootOpcode }, + /*0x15E*/ { "CMSG_LOOT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleLootMoneyOpcode }, + /*0x15F*/ { "CMSG_LOOT_RELEASE", STATUS_LOGGEDIN, &WorldSession::HandleLootReleaseOpcode }, + /*0x160*/ { "SMSG_LOOT_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x161*/ { "SMSG_LOOT_RELEASE_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x162*/ { "SMSG_LOOT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x163*/ { "SMSG_LOOT_MONEY_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x164*/ { "SMSG_LOOT_ITEM_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x165*/ { "SMSG_LOOT_CLEAR_MONEY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x166*/ { "SMSG_ITEM_PUSH_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x167*/ { "SMSG_DUEL_REQUESTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x168*/ { "SMSG_DUEL_OUTOFBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x169*/ { "SMSG_DUEL_INBOUNDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16A*/ { "SMSG_DUEL_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16B*/ { "SMSG_DUEL_WINNER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16C*/ { "CMSG_DUEL_ACCEPTED", STATUS_LOGGEDIN, &WorldSession::HandleDuelAcceptedOpcode }, + /*0x16D*/ { "CMSG_DUEL_CANCELLED", STATUS_LOGGEDIN, &WorldSession::HandleDuelCancelledOpcode }, + /*0x16E*/ { "SMSG_MOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x16F*/ { "SMSG_DISMOUNTRESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x170*/ { "SMSG_PUREMOUNT_CANCELLED_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x171*/ { "CMSG_MOUNTSPECIAL_ANIM", STATUS_LOGGEDIN, &WorldSession::HandleMountSpecialAnimOpcode }, + /*0x172*/ { "SMSG_MOUNTSPECIAL_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x173*/ { "SMSG_PET_TAME_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x174*/ { "CMSG_PET_SET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetSetAction }, + /*0x175*/ { "CMSG_PET_ACTION", STATUS_LOGGEDIN, &WorldSession::HandlePetAction }, + /*0x176*/ { "CMSG_PET_ABANDON", STATUS_LOGGEDIN, &WorldSession::HandlePetAbandon }, + /*0x177*/ { "CMSG_PET_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetRename }, + /*0x178*/ { "SMSG_PET_NAME_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x179*/ { "SMSG_PET_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17A*/ { "SMSG_PET_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17B*/ { "CMSG_GOSSIP_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleGossipHelloOpcode }, + /*0x17C*/ { "CMSG_GOSSIP_SELECT_OPTION", STATUS_LOGGEDIN, &WorldSession::HandleGossipSelectOptionOpcode }, + /*0x17D*/ { "SMSG_GOSSIP_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17E*/ { "SMSG_GOSSIP_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x17F*/ { "CMSG_NPC_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleNpcTextQueryOpcode }, + /*0x180*/ { "SMSG_NPC_TEXT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x181*/ { "SMSG_NPC_WONT_TALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x182*/ { "CMSG_QUESTGIVER_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryOpcode}, + /*0x183*/ { "SMSG_QUESTGIVER_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x184*/ { "CMSG_QUESTGIVER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverHelloOpcode }, + /*0x185*/ { "SMSG_QUESTGIVER_QUEST_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x186*/ { "CMSG_QUESTGIVER_QUERY_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverQuestQueryOpcode}, + /*0x187*/ { "CMSG_QUESTGIVER_QUEST_AUTOLAUNCH", STATUS_LOGGEDIN, &WorldSession::HandleQuestAutoLaunch }, + /*0x188*/ { "SMSG_QUESTGIVER_QUEST_DETAILS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x189*/ { "CMSG_QUESTGIVER_ACCEPT_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverAcceptQuestOpcode}, + /*0x18A*/ { "CMSG_QUESTGIVER_COMPLETE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestComplete }, + /*0x18B*/ { "SMSG_QUESTGIVER_REQUEST_ITEMS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x18C*/ { "CMSG_QUESTGIVER_REQUEST_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverRequestRewardOpcode}, + /*0x18D*/ { "SMSG_QUESTGIVER_OFFER_REWARD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x18E*/ { "CMSG_QUESTGIVER_CHOOSE_REWARD", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverChooseRewardOpcode}, + /*0x18F*/ { "SMSG_QUESTGIVER_QUEST_INVALID", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x190*/ { "CMSG_QUESTGIVER_CANCEL", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverCancel }, + /*0x191*/ { "SMSG_QUESTGIVER_QUEST_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x192*/ { "SMSG_QUESTGIVER_QUEST_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x193*/ { "CMSG_QUESTLOG_SWAP_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogSwapQuest }, + /*0x194*/ { "CMSG_QUESTLOG_REMOVE_QUEST", STATUS_LOGGEDIN, &WorldSession::HandleQuestLogRemoveQuest }, + /*0x195*/ { "SMSG_QUESTLOG_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x196*/ { "SMSG_QUESTUPDATE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x197*/ { "SMSG_QUESTUPDATE_FAILEDTIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x198*/ { "SMSG_QUESTUPDATE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x199*/ { "SMSG_QUESTUPDATE_ADD_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19A*/ { "SMSG_QUESTUPDATE_ADD_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19B*/ { "CMSG_QUEST_CONFIRM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleQuestConfirmAccept }, + /*0x19C*/ { "SMSG_QUEST_CONFIRM_ACCEPT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x19D*/ { "CMSG_PUSHQUESTTOPARTY", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushToParty }, + /*0x19E*/ { "CMSG_LIST_INVENTORY", STATUS_LOGGEDIN, &WorldSession::HandleListInventoryOpcode }, + /*0x19F*/ { "SMSG_LIST_INVENTORY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A0*/ { "CMSG_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleSellItemOpcode }, + /*0x1A1*/ { "SMSG_SELL_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A2*/ { "CMSG_BUY_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemOpcode }, + /*0x1A3*/ { "CMSG_BUY_ITEM_IN_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyItemInSlotOpcode }, + /*0x1A4*/ { "SMSG_BUY_ITEM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A5*/ { "SMSG_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1A6*/ { "CMSG_TAXICLEARALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A7*/ { "CMSG_TAXIENABLEALLNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A8*/ { "CMSG_TAXISHOWNODES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1A9*/ { "SMSG_SHOWTAXINODES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AA*/ { "CMSG_TAXINODE_STATUS_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNodeStatusQueryOpcode }, + /*0x1AB*/ { "SMSG_TAXINODE_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AC*/ { "CMSG_TAXIQUERYAVAILABLENODES", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodes }, + /*0x1AD*/ { "CMSG_ACTIVATETAXI", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiOpcode }, + /*0x1AE*/ { "SMSG_ACTIVATETAXIREPLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1AF*/ { "SMSG_NEW_TAXI_PATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B0*/ { "CMSG_TRAINER_LIST", STATUS_LOGGEDIN, &WorldSession::HandleTrainerListOpcode }, + /*0x1B1*/ { "SMSG_TRAINER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B2*/ { "CMSG_TRAINER_BUY_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleTrainerBuySpellOpcode }, + /*0x1B3*/ { "SMSG_TRAINER_BUY_SUCCEEDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B4*/ { "SMSG_TRAINER_BUY_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B5*/ { "CMSG_BINDER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBinderActivateOpcode }, + /*0x1B6*/ { "SMSG_PLAYERBINDERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B7*/ { "CMSG_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleBankerActivateOpcode }, + /*0x1B8*/ { "SMSG_SHOW_BANK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1B9*/ { "CMSG_BUY_BANK_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyBankSlotOpcode }, + /*0x1BA*/ { "SMSG_BUY_BANK_SLOT_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1BB*/ { "CMSG_PETITION_SHOWLIST", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowListOpcode }, + /*0x1BC*/ { "SMSG_PETITION_SHOWLIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1BD*/ { "CMSG_PETITION_BUY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionBuyOpcode }, + /*0x1BE*/ { "CMSG_PETITION_SHOW_SIGNATURES", STATUS_LOGGEDIN, &WorldSession::HandlePetitionShowSignOpcode }, + /*0x1BF*/ { "SMSG_PETITION_SHOW_SIGNATURES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C0*/ { "CMSG_PETITION_SIGN", STATUS_LOGGEDIN, &WorldSession::HandlePetitionSignOpcode }, + /*0x1C1*/ { "SMSG_PETITION_SIGN_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C2*/ { "MSG_PETITION_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandlePetitionDeclineOpcode }, + /*0x1C3*/ { "CMSG_OFFER_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleOfferPetitionOpcode }, + /*0x1C4*/ { "CMSG_TURN_IN_PETITION", STATUS_LOGGEDIN, &WorldSession::HandleTurnInPetitionOpcode }, + /*0x1C5*/ { "SMSG_TURN_IN_PETITION_RESULTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C6*/ { "CMSG_PETITION_QUERY", STATUS_LOGGEDIN, &WorldSession::HandlePetitionQueryOpcode }, + /*0x1C7*/ { "SMSG_PETITION_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C8*/ { "SMSG_FISH_NOT_HOOKED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1C9*/ { "SMSG_FISH_ESCAPED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CA*/ { "CMSG_BUG", STATUS_LOGGEDIN, &WorldSession::HandleBugOpcode }, + /*0x1CB*/ { "SMSG_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CC*/ { "CMSG_PLAYED_TIME", STATUS_LOGGEDIN, &WorldSession::HandlePlayedTime }, + /*0x1CD*/ { "SMSG_PLAYED_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1CE*/ { "CMSG_QUERY_TIME", STATUS_LOGGEDIN, &WorldSession::HandleQueryTimeOpcode }, + /*0x1CF*/ { "SMSG_QUERY_TIME_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D0*/ { "SMSG_LOG_XPGAIN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D1*/ { "SMSG_AURACASTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D2*/ { "CMSG_RECLAIM_CORPSE", STATUS_LOGGEDIN, &WorldSession::HandleCorpseReclaimOpcode }, + /*0x1D3*/ { "CMSG_WRAP_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleWrapItemOpcode }, + /*0x1D4*/ { "SMSG_LEVELUP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D5*/ { "MSG_MINIMAP_PING", STATUS_LOGGEDIN, &WorldSession::HandleMinimapPingOpcode }, + /*0x1D6*/ { "SMSG_RESISTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D7*/ { "SMSG_ENCHANTMENTLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1D8*/ { "CMSG_SET_SKILL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1D9*/ { "SMSG_START_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DA*/ { "SMSG_PAUSE_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DB*/ { "SMSG_STOP_MIRROR_TIMER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DC*/ { "CMSG_PING", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x1DD*/ { "SMSG_PONG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DE*/ { "SMSG_CLEAR_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1DF*/ { "SMSG_GAMEOBJECT_PAGETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E0*/ { "CMSG_SETSHEATHED", STATUS_LOGGEDIN, &WorldSession::HandleSetSheathedOpcode }, + /*0x1E1*/ { "SMSG_COOLDOWN_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E2*/ { "SMSG_SPELL_DELAYED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E3*/ { "CMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E4*/ { "SMSG_PLAYER_MACRO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E5*/ { "CMSG_GHOST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E6*/ { "CMSG_GM_INVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E7*/ { "SMSG_INVALID_PROMOTION_CODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1E8*/ { "MSG_GM_BIND_OTHER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1E9*/ { "MSG_GM_SUMMON", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1EA*/ { "SMSG_ITEM_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EB*/ { "SMSG_ITEM_ENCHANT_TIME_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EC*/ { "SMSG_AUTH_CHALLENGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1ED*/ { "CMSG_AUTH_SESSION", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x1EE*/ { "SMSG_AUTH_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1EF*/ { "MSG_GM_SHOWLABEL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1F0*/ { "CMSG_PET_CAST_SPELL", STATUS_LOGGEDIN, &WorldSession::HandlePetCastSpellOpcode }, + /*0x1F1*/ { "MSG_SAVE_GUILD_EMBLEM", STATUS_LOGGEDIN, &WorldSession::HandleGuildSaveEmblemOpcode }, + /*0x1F2*/ { "MSG_TABARDVENDOR_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleTabardVendorActivateOpcode}, + /*0x1F3*/ { "SMSG_PLAY_SPELL_VISUAL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F4*/ { "CMSG_ZONEUPDATE", STATUS_LOGGEDIN, &WorldSession::HandleZoneUpdateOpcode }, + /*0x1F5*/ { "SMSG_PARTYKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F6*/ { "SMSG_COMPRESSED_UPDATE_OBJECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F7*/ { "SMSG_PLAY_SPELL_IMPACT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F8*/ { "SMSG_EXPLORATION_EXPERIENCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1F9*/ { "CMSG_GM_SET_SECURITY_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FA*/ { "CMSG_GM_NUKE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FB*/ { "MSG_RANDOM_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleRandomRollOpcode }, + /*0x1FC*/ { "SMSG_ENVIRONMENTALDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1FD*/ { "CMSG_RWHOIS_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x1FE*/ { "SMSG_RWHOIS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x1FF*/ { "MSG_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLookingForGroup }, + /*0x200*/ { "CMSG_SET_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleSetLfgOpcode }, + /*0x201*/ { "CMSG_UNLEARN_SPELL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x202*/ { "CMSG_UNLEARN_SKILL", STATUS_LOGGEDIN, &WorldSession::HandleUnlearnSkillOpcode }, + /*0x203*/ { "SMSG_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x204*/ { "CMSG_DECHARGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x205*/ { "CMSG_GMTICKET_CREATE", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketCreateOpcode }, + /*0x206*/ { "SMSG_GMTICKET_CREATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x207*/ { "CMSG_GMTICKET_UPDATETEXT", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketUpdateOpcode }, - /*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleRequestAccountData }, - /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleUpdateAccountData }, - /*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20E*/ { "SMSG_POWERGAINLOG_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x20F*/ { "CMSG_GM_TEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x210*/ { "CMSG_GM_CREATE_ITEM_TARGET", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x211*/ { "CMSG_GMTICKET_GETTICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketGetTicketOpcode }, - /*0x212*/ { "SMSG_GMTICKET_GETTICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x213*/ { "CMSG_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x214*/ { "SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x215*/ { "SMSG_GAMEOBJECT_DESPAWN_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x216*/ { "MSG_CORPSE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseQueryOpcode }, - /*0x217*/ { "CMSG_GMTICKET_DELETETICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketDeleteOpcode }, - /*0x218*/ { "SMSG_GMTICKET_DELETETICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x219*/ { "SMSG_CHAT_WRONG_FACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x21A*/ { "CMSG_GMTICKET_SYSTEMSTATUS", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketSystemStatusOpcode}, - /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode}, - /*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x21E*/ { "SMSG_SET_REST_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x222*/ { "SMSG_SPIRIT_HEALER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x223*/ { "CMSG_CHARACTER_POINT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x224*/ { "SMSG_GOSSIP_POI", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x225*/ { "CMSG_CHAT_IGNORED", STATUS_LOGGEDIN, &WorldSession::HandleChatIgnoredOpcode }, - /*0x226*/ { "CMSG_GM_VISION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x227*/ { "CMSG_SERVER_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x228*/ { "CMSG_GM_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x229*/ { "CMSG_GM_REVEALTO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22A*/ { "CMSG_GM_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22B*/ { "CMSG_GM_SUMMONMOB", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22C*/ { "CMSG_GM_MOVECORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22D*/ { "CMSG_GM_FREEZE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22E*/ { "CMSG_GM_UBERINVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x22F*/ { "CMSG_GM_REQUEST_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x230*/ { "SMSG_GM_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x231*/ { "CMSG_GUILD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildRankOpcode }, - /*0x232*/ { "CMSG_GUILD_ADD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildAddRankOpcode }, - /*0x233*/ { "CMSG_GUILD_DEL_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildDelRankOpcode }, - /*0x234*/ { "CMSG_GUILD_SET_PUBLIC_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetPublicNoteOpcode }, - /*0x235*/ { "CMSG_GUILD_SET_OFFICER_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetOfficerNoteOpcode }, - /*0x236*/ { "SMSG_LOGIN_VERIFY_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x237*/ { "CMSG_CLEAR_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x238*/ { "CMSG_SEND_MAIL", STATUS_LOGGEDIN, &WorldSession::HandleSendMail }, - /*0x239*/ { "SMSG_SEND_MAIL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x23A*/ { "CMSG_GET_MAIL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleGetMail }, - /*0x23B*/ { "SMSG_MAIL_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x23C*/ { "CMSG_BATTLEFIELD_LIST", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundListOpcode }, - /*0x23D*/ { "SMSG_BATTLEFIELD_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x23E*/ { "CMSG_BATTLEFIELD_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x23F*/ { "SMSG_BATTLEFIELD_WIN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x240*/ { "SMSG_BATTLEFIELD_LOSE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x241*/ { "CMSG_TAXICLEARNODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x242*/ { "CMSG_TAXIENABLENODE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x243*/ { "CMSG_ITEM_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemTextQuery }, - /*0x244*/ { "SMSG_ITEM_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x245*/ { "CMSG_MAIL_TAKE_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleTakeMoney }, - /*0x246*/ { "CMSG_MAIL_TAKE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleTakeItem }, - /*0x247*/ { "CMSG_MAIL_MARK_AS_READ", STATUS_LOGGEDIN, &WorldSession::HandleMarkAsRead }, - /*0x248*/ { "CMSG_MAIL_RETURN_TO_SENDER", STATUS_LOGGEDIN, &WorldSession::HandleReturnToSender }, - /*0x249*/ { "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleMailDelete }, - /*0x24A*/ { "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleMailCreateTextItem }, - /*0x24B*/ { "SMSG_SPELLLOGMISS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24C*/ { "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24D*/ { "SMSG_DEBUGAURAPROC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24E*/ { "SMSG_PERIODICAURALOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x24F*/ { "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x250*/ { "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x251*/ { "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandleLearnTalentOpcode }, - /*0x252*/ { "SMSG_RESURRECT_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x253*/ { "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, &WorldSession::HandleTogglePvP }, - /*0x254*/ { "SMSG_ZONE_UNDER_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x255*/ { "MSG_AUCTION_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleAuctionHelloOpcode }, - /*0x256*/ { "CMSG_AUCTION_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionSellItem }, - /*0x257*/ { "CMSG_AUCTION_REMOVE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionRemoveItem }, - /*0x258*/ { "CMSG_AUCTION_LIST_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListItems }, - /*0x259*/ { "CMSG_AUCTION_LIST_OWNER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListOwnerItems }, - /*0x25A*/ { "CMSG_AUCTION_PLACE_BID", STATUS_LOGGEDIN, &WorldSession::HandleAuctionPlaceBid }, - /*0x25B*/ { "SMSG_AUCTION_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25C*/ { "SMSG_AUCTION_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25D*/ { "SMSG_AUCTION_OWNER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25E*/ { "SMSG_AUCTION_BIDDER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x25F*/ { "SMSG_AUCTION_OWNER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x260*/ { "SMSG_PROCRESIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x261*/ { "SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE",STATUS_NEVER,&WorldSession::Handle_ServerSide }, - /*0x262*/ { "SMSG_DISPEL_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x263*/ { "SMSG_SPELLORDAMAGE_IMMUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x264*/ { "CMSG_AUCTION_LIST_BIDDER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListBidderItems }, - /*0x265*/ { "SMSG_AUCTION_BIDDER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x266*/ { "SMSG_SET_FLAT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x267*/ { "SMSG_SET_PCT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x268*/ { "CMSG_SET_AMMO", STATUS_LOGGEDIN, &WorldSession::HandleSetAmmoOpcode }, - /*0x269*/ { "SMSG_CORPSE_RECLAIM_DELAY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x26A*/ { "CMSG_SET_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleSetActiveMoverOpcode }, - /*0x26B*/ { "CMSG_PET_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandlePetCancelAuraOpcode }, - /*0x26C*/ { "CMSG_PLAYER_AI_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x26D*/ { "CMSG_CANCEL_AUTO_REPEAT_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCancelAutoRepeatSpellOpcode}, - /*0x26E*/ { "MSG_GM_ACCOUNT_ONLINE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x26F*/ { "MSG_LIST_STABLED_PETS", STATUS_LOGGEDIN, &WorldSession::HandleListStabledPetsOpcode }, - /*0x270*/ { "CMSG_STABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStablePet }, - /*0x271*/ { "CMSG_UNSTABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleUnstablePet }, - /*0x272*/ { "CMSG_BUY_STABLE_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyStableSlot }, - /*0x273*/ { "SMSG_STABLE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x274*/ { "CMSG_STABLE_REVIVE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableRevivePet }, - /*0x275*/ { "CMSG_STABLE_SWAP_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableSwapPet }, - /*0x276*/ { "MSG_QUEST_PUSH_RESULT", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushResult }, - /*0x277*/ { "SMSG_PLAY_MUSIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x278*/ { "SMSG_PLAY_OBJECT_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x279*/ { "CMSG_REQUEST_PET_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestPetInfoOpcode }, - /*0x27A*/ { "CMSG_FAR_SIGHT", STATUS_LOGGEDIN, &WorldSession::HandleFarSightOpcode }, - /*0x27B*/ { "SMSG_SPELLDISPELLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x27C*/ { "SMSG_DAMAGE_CALC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x27D*/ { "CMSG_ENABLE_DAMAGE_LOG", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x27E*/ { "CMSG_GROUP_CHANGE_SUB_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleGroupChangeSubGroupOpcode }, - /*0x27F*/ { "CMSG_REQUEST_PARTY_MEMBER_STATS", STATUS_LOGGEDIN, &WorldSession::HandleRequestPartyMemberStatsOpcode}, - /*0x280*/ { "CMSG_GROUP_SWAP_SUB_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x281*/ { "CMSG_RESET_FACTION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x282*/ { "CMSG_AUTOSTORE_BANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBankItemOpcode }, - /*0x283*/ { "CMSG_AUTOBANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoBankItemOpcode }, - /*0x284*/ { "MSG_QUERY_NEXT_MAIL_TIME", STATUS_LOGGEDIN, &WorldSession::HandleMsgQueryNextMailtime }, - /*0x285*/ { "SMSG_RECEIVED_MAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x286*/ { "SMSG_RAID_GROUP_ONLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x287*/ { "CMSG_SET_DURABILITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x288*/ { "CMSG_SET_PVP_RANK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x289*/ { "CMSG_ADD_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x28A*/ { "CMSG_DEL_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x28B*/ { "CMSG_SET_PVP_TITLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x28C*/ { "SMSG_PVP_CREDIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x28D*/ { "SMSG_AUCTION_REMOVED_NOTIFICATION",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x28E*/ { "CMSG_GROUP_RAID_CONVERT", STATUS_LOGGEDIN, &WorldSession::HandleRaidConvertOpcode }, - /*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupAssistantOpcode }, - /*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuybackItem }, - /*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x292*/ { "CMSG_MEETINGSTONE_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x293*/ { "CMSG_MEETINGSTONE_LEAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x294*/ { "CMSG_MEETINGSTONE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x295*/ { "SMSG_MEETINGSTONE_SETQUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x296*/ { "CMSG_MEETINGSTONE_INFO", STATUS_LOGGEDIN, &WorldSession::HandleMeetingStoneInfo }, - /*0x297*/ { "SMSG_MEETINGSTONE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x298*/ { "SMSG_MEETINGSTONE_IN_PROGRESS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x299*/ { "SMSG_MEETINGSTONE_MEMBER_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29A*/ { "CMSG_GMTICKETSYSTEM_TOGGLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x29B*/ { "CMSG_CANCEL_GROWTH_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelGrowthAuraOpcode }, - /*0x29C*/ { "SMSG_CANCEL_AUTO_REPEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29D*/ { "SMSG_STANDSTATE_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29E*/ { "SMSG_LOOT_ALL_PASSED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x29F*/ { "SMSG_LOOT_ROLL_WON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A0*/ { "CMSG_LOOT_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleLootRoll }, - /*0x2A1*/ { "SMSG_LOOT_START_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A2*/ { "SMSG_LOOT_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A3*/ { "CMSG_LOOT_MASTER_GIVE", STATUS_LOGGEDIN, &WorldSession::HandleLootMasterGiveOpcode }, - /*0x2A4*/ { "SMSG_LOOT_MASTER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A5*/ { "SMSG_SET_FORCED_REACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A6*/ { "SMSG_SPELL_FAILED_OTHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A7*/ { "SMSG_GAMEOBJECT_RESET_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2A8*/ { "CMSG_REPAIR_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleRepairItemOpcode }, - /*0x2A9*/ { "SMSG_CHAT_PLAYER_NOT_FOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2AA*/ { "MSG_TALENT_WIPE_CONFIRM", STATUS_LOGGEDIN, &WorldSession::HandleTalentWipeOpcode }, - /*0x2AB*/ { "SMSG_SUMMON_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2AC*/ { "CMSG_SUMMON_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleSummonResponseOpcode }, - /*0x2AD*/ { "MSG_MOVE_TOGGLE_GRAVITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2AE*/ { "SMSG_MONSTER_MOVE_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2AF*/ { "SMSG_PET_BROKEN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B0*/ { "MSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B1*/ { "MSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B2*/ { "CMSG_SERVER_BROADCAST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B3*/ { "CMSG_SELF_RES", STATUS_LOGGEDIN, &WorldSession::HandleSelfResOpcode }, - /*0x2B4*/ { "SMSG_FEIGN_DEATH_RESISTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B5*/ { "CMSG_RUN_SCRIPT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2B6*/ { "SMSG_SCRIPT_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B7*/ { "SMSG_DUEL_COUNTDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B8*/ { "SMSG_AREA_TRIGGER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2B9*/ { "CMSG_TOGGLE_HELM", STATUS_LOGGEDIN, &WorldSession::HandleToggleHelmOpcode }, - /*0x2BA*/ { "CMSG_TOGGLE_CLOAK", STATUS_LOGGEDIN, &WorldSession::HandleToggleCloakOpcode }, - /*0x2BB*/ { "SMSG_MEETINGSTONE_JOINFAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2BC*/ { "SMSG_PLAYER_SKINNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2BD*/ { "SMSG_DURABILITY_DAMAGE_DEATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2BE*/ { "CMSG_SET_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2BF*/ { "CMSG_SET_ACTIONBAR_TOGGLES", STATUS_AUTHED, &WorldSession::HandleSetActionBar }, - /*0x2C0*/ { "UMSG_DELETE_GUILD_CHARTER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2C1*/ { "MSG_PETITION_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetitionRenameOpcode }, - /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemNameQueryOpcode }, - /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, &WorldSession::HandleChangePlayerNameOpcode }, - /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNextDestinationOpcode }, - /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestRaidInfoOpcode }, - /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, &WorldSession::HandleMoveTimeSkippedOpcode }, - /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, &WorldSession::HandleFeatherFallAck }, - /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveWaterWalkAck }, - /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleNotActiveMoverOpcode }, - /*0x2D2*/ { "SMSG_PLAY_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2D3*/ { "CMSG_BATTLEFIELD_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldStatusOpcode }, - /*0x2D4*/ { "SMSG_BATTLEFIELD_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2D5*/ { "CMSG_BATTLEFIELD_PORT", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPortOpcode}, - /*0x2D6*/ { "MSG_INSPECT_HONOR_STATS", STATUS_LOGGEDIN, &WorldSession::HandleInspectHonorStatsOpcode }, - /*0x2D7*/ { "CMSG_BATTLEMASTER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundHelloOpcode }, - /*0x2D8*/ { "CMSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2D9*/ { "CMSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2DA*/ { "SMSG_FORCE_WALK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2DB*/ { "CMSG_FORCE_WALK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x2DC*/ { "SMSG_FORCE_SWIM_BACK_SPEED_CHANGE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2DD*/ { "CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, - /*0x2DE*/ { "SMSG_FORCE_TURN_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2DF*/ { "CMSG_FORCE_TURN_RATE_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, - /*0x2E0*/ { "MSG_PVP_LOG_DATA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPVPlogdataOpcode}, - /*0x2E1*/ { "CMSG_LEAVE_BATTLEFIELD", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundLeaveOpcode }, - /*0x2E2*/ { "CMSG_AREA_SPIRIT_HEALER_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueryOpcode}, - /*0x2E3*/ { "CMSG_AREA_SPIRIT_HEALER_QUEUE", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueueOpcode}, - /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2E5*/ { "CMSG_GM_UNTEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2E6*/ { "SMSG_WARDEN_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2E7*/ { "CMSG_WARDEN_DATA", STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode }, - /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS",STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPositionsOpcode}, - /*0x2EA*/ { "CMSG_PET_STOP_ATTACK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2EB*/ { "SMSG_BINDER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2EC*/ { "SMSG_BATTLEGROUND_PLAYER_JOINED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundJoinOpcode }, - /*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_LOGGEDIN, &WorldSession::HandlePetUnlearnOpcode }, - /*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, &WorldSession::HandlePetSpellAutocastOpcode }, - /*0x2F4*/ { "SMSG_WEATHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F5*/ { "SMSG_PLAY_TIME_WARNING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F6*/ { "SMSG_MINIGAME_SETUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F7*/ { "SMSG_MINIGAME_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2F8*/ { "CMSG_MINIGAME_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x2F9*/ { "SMSG_MINIGAME_MOVE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FA*/ { "SMSG_RAID_INSTANCE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FB*/ { "SMSG_COMPRESSED_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FC*/ { "CMSG_GUILD_INFO_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildChangeInfoOpcode }, - /*0x2FD*/ { "SMSG_CHAT_RESTRICTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FE*/ { "SMSG_SPLINE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x2FF*/ { "SMSG_SPLINE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x300*/ { "SMSG_SPLINE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x301*/ { "SMSG_SPLINE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x302*/ { "SMSG_SPLINE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x303*/ { "SMSG_SPLINE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x304*/ { "SMSG_SPLINE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x305*/ { "SMSG_SPLINE_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x306*/ { "SMSG_SPLINE_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x307*/ { "SMSG_SPLINE_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x308*/ { "SMSG_SPLINE_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x309*/ { "SMSG_SPLINE_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30A*/ { "SMSG_SPLINE_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30B*/ { "SMSG_SPLINE_MOVE_START_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30C*/ { "SMSG_SPLINE_MOVE_STOP_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30D*/ { "SMSG_SPLINE_MOVE_SET_RUN_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30E*/ { "SMSG_SPLINE_MOVE_SET_WALK_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x30F*/ { "CMSG_GM_NUKE_ACCOUNT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x310*/ { "MSG_GM_DESTROY_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x311*/ { "CMSG_GM_DESTROY_ONLINE_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x312*/ { "CMSG_ACTIVATETAXIEXPRESS", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiFarOpcode }, - /*0x313*/ { "SMSG_SET_FACTION_ATWAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x314*/ { "SMSG_GAMETIMEBIAS_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x315*/ { "CMSG_DEBUG_ACTIONS_START", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x316*/ { "CMSG_DEBUG_ACTIONS_STOP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x317*/ { "CMSG_SET_FACTION_INACTIVE", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionInactiveOpcode}, - /*0x318*/ { "CMSG_SET_WATCHED_FACTION", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionIndexOpcode}, - /*0x319*/ { "MSG_MOVE_TIME_SKIPPED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x31A*/ { "SMSG_SPLINE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x31B*/ { "CMSG_SET_EXPLORATION_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x31C*/ { "SMSG_INVALIDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x31D*/ { "CMSG_RESET_INSTANCES", STATUS_LOGGEDIN, &WorldSession::HandleResetInstancesOpcode }, - /*0x31E*/ { "SMSG_INSTANCE_RESET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x31F*/ { "SMSG_INSTANCE_RESET_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x320*/ { "SMSG_UPDATE_LAST_INSTANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x321*/ { "MSG_RAID_TARGET_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleRaidIconTargetOpcode }, - /*0x322*/ { "MSG_RAID_READY_CHECK", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckOpcode }, - /*0x323*/ { "CMSG_LUA_USAGE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x324*/ { "SMSG_PET_ACTION_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x325*/ { "SMSG_PET_DISMISS_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x326*/ { "SMSG_GHOSTEE_GONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x327*/ { "CMSG_GM_UPDATE_TICKET_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x328*/ { "SMSG_GM_TICKET_STATUS_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x329*/ { "MSG_SET_DUNGEON_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleDungeonDifficultyOpcode }, - /*0x32A*/ { "CMSG_GMSURVEY_SUBMIT", STATUS_LOGGEDIN, &WorldSession::Handle_NULL },//&WorldSession::HandleGMSurveySubmit - /*0x32B*/ { "SMSG_UPDATE_INSTANCE_OWNERSHIP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x32C*/ { "CMSG_IGNORE_KNOCKBACK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x32D*/ { "SMSG_CHAT_PLAYER_AMBIGUOUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x32E*/ { "MSG_DELAY_GHOST_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x32F*/ { "SMSG_SPELLINSTAKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x330*/ { "SMSG_SPELL_UPDATE_CHAIN_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x331*/ { "CMSG_CHAT_FILTERED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x332*/ { "SMSG_EXPECTED_SPAM_RECORDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x333*/ { "SMSG_SPELLSTEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x334*/ { "CMSG_LOTTERY_QUERY_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x335*/ { "SMSG_LOTTERY_QUERY_RESULT_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x336*/ { "CMSG_BUY_LOTTERY_TICKET_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x337*/ { "SMSG_LOTTERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x338*/ { "SMSG_CHARACTER_PROFILE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x339*/ { "SMSG_CHARACTER_PROFILE_REALM_CONNECTED",STATUS_NEVER,&WorldSession::Handle_ServerSide }, - /*0x33A*/ { "SMSG_DEFENSE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33B*/ { "SMSG_INSTANCE_DIFFICULTY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33C*/ { "MSG_GM_RESETINSTANCELIMIT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x33D*/ { "SMSG_MOTD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33E*/ { "SMSG_MOVE_SET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x33F*/ { "SMSG_MOVE_UNSET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x340*/ { "CMSG_MOVE_FLIGHT_ACK_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x341*/ { "MSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x342*/ { "MSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x343*/ { "SMSG_MOVE_SET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x344*/ { "SMSG_MOVE_UNSET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x345*/ { "CMSG_MOVE_SET_CAN_FLY_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveFlyModeChangeAckOpcode}, - /*0x346*/ { "CMSG_MOVE_SET_FLY", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x347*/ { "CMSG_SOCKET_GEMS", STATUS_LOGGEDIN, &WorldSession::HandleSocketOpcode }, - /*0x348*/ { "CMSG_ARENA_TEAM_CREATE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x349*/ { "SMSG_ARENA_TEAM_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x34A*/ { "UMSG_UPDATE_ARENA_TEAM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x34B*/ { "CMSG_ARENA_TEAM_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamQueryOpcode }, - /*0x34C*/ { "SMSG_ARENA_TEAM_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x34D*/ { "CMSG_ARENA_TEAM_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRosterOpcode }, - /*0x34E*/ { "SMSG_ARENA_TEAM_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x34F*/ { "CMSG_ARENA_TEAM_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamAddMemberOpcode }, - /*0x350*/ { "SMSG_ARENA_TEAM_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x351*/ { "CMSG_ARENA_TEAM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteAcceptOpcode}, - /*0x352*/ { "CMSG_ARENA_TEAM_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteDeclineOpcode}, - /*0x353*/ { "CMSG_ARENA_TEAM_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaveOpcode }, - /*0x354*/ { "CMSG_ARENA_TEAM_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRemoveFromTeamOpcode}, - /*0x355*/ { "CMSG_ARENA_TEAM_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDisbandOpcode }, - /*0x356*/ { "CMSG_ARENA_TEAM_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamPromoteToCaptainOpcode}, - /*0x357*/ { "SMSG_ARENA_TEAM_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x358*/ { "CMSG_BATTLEMASTER_JOIN_ARENA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundArenaJoin }, - /*0x359*/ { "MSG_MOVE_START_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x35A*/ { "MSG_MOVE_STOP_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x35C*/ { "CMSG_LFG_SET_AUTOJOIN", STATUS_AUTHED, &WorldSession::HandleLfgAutoJoinOpcode }, - /*0x35D*/ { "CMSG_LFG_CLEAR_AUTOJOIN", STATUS_LOGGEDIN, &WorldSession::HandleLfgCancelAutoJoinOpcode }, - /*0x35E*/ { "CMSG_LFM_SET_AUTOFILL", STATUS_AUTHED, &WorldSession::HandleLfmAutoAddMembersOpcode }, - /*0x35F*/ { "CMSG_LFM_CLEAR_AUTOFILL", STATUS_LOGGEDIN, &WorldSession::HandleLfmCancelAutoAddmembersOpcode}, - /*0x360*/ { "CMSG_ACCEPT_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x361*/ { "CMSG_DECLINE_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x362*/ { "CMSG_CANCEL_PENDING_LFG", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x363*/ { "CMSG_CLEAR_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLfgClearOpcode }, - /*0x364*/ { "CMSG_CLEAR_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetNoneOpcode }, - /*0x365*/ { "CMSG_SET_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetOpcode }, - /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetCommentOpcode }, - /*0x367*/ { "SMSG_LFG_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x368*/ { "SMSG_LFG_OTHER_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x369*/ { "SMSG_LFG_AUTOJOIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36A*/ { "SMSG_LFG_AUTOJOIN_FAILED_NO_PLAYER",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36B*/ { "SMSG_LFG_LEADER_IS_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36C*/ { "SMSG_LFG_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36D*/ { "SMSG_LFG_UPDATE_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36E*/ { "SMSG_LFG_UPDATE_LFG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x36F*/ { "SMSG_LFG_UPDATE_QUEUED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x370*/ { "SMSG_LFG_PENDING_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x371*/ { "SMSG_LFG_PENDING_MATCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x372*/ { "SMSG_LFG_PENDING_MATCH_DONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, &WorldSession::HandleChooseTitleOpcode }, - /*0x375*/ { "CMSG_CANCEL_MOUNT_AURA", STATUS_LOGGEDIN, &WorldSession::HandleDismountOpcode }, - /*0x376*/ { "SMSG_ARENA_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x377*/ { "MSG_INSPECT_ARENA_TEAMS", STATUS_LOGGEDIN, &WorldSession::HandleInspectArenaStatsOpcode }, - /*0x378*/ { "SMSG_DEATH_RELEASE_LOC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x379*/ { "CMSG_CANCEL_TEMP_ENCHANTMENT", STATUS_LOGGEDIN, &WorldSession::HandleCancelTempItemEnchantmentOpcode}, - /*0x37A*/ { "SMSG_FORCED_DEATH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x37B*/ { "CMSG_CHEAT_SET_HONOR_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37C*/ { "CMSG_CHEAT_SET_ARENA_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37D*/ { "MSG_MOVE_SET_FLIGHT_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37E*/ { "MSG_MOVE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x37F*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT",STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x380*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x381*/ { "SMSG_FORCE_FLIGHT_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x382*/ { "CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, - /*0x383*/ { "SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x384*/ { "CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK",STATUS_LOGGEDIN,&WorldSession::HandleForceSpeedChangeAck }, - /*0x385*/ { "SMSG_SPLINE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, &WorldSession::HandleSetTaxiBenchmarkOpcode }, - /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, &WorldSession::HandleRealmStateRequestOpcode }, - /*0x38D*/ { "CMSG_MOVE_CHNG_TRANSPORT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x38E*/ { "MSG_PARTY_ASSIGNMENT", STATUS_LOGGEDIN, &WorldSession::HandleGroupPromoteOpcode }, - /*0x38F*/ { "SMSG_OFFER_PETITION_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x390*/ { "SMSG_TIME_SYNC_REQ", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x391*/ { "CMSG_TIME_SYNC_RESP", STATUS_LOGGEDIN, &WorldSession::HandleAllowMoveAckOpcode }, - /*0x392*/ { "CMSG_SEND_LOCAL_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x393*/ { "CMSG_SEND_GENERAL_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x394*/ { "CMSG_SEND_COMBAT_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x395*/ { "CMSG_MAELSTROM_GM_SENT_MAIL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x396*/ { "SMSG_RESET_FAILED_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x397*/ { "SMSG_REAL_GROUP_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x398*/ { "SMSG_LFG_DISABLED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x399*/ { "CMSG_ACTIVE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x39A*/ { "CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x39B*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE",STATUS_NEVER,&WorldSession::Handle_ServerSide }, - /*0x39C*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE",STATUS_NEVER,&WorldSession::Handle_ServerSide}, - /*0x39D*/ { "SMSG_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x39E*/ { "SMSG_VOICE_SESSION_ROSTER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x39F*/ { "SMSG_VOICE_SESSION_LEAVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A0*/ { "SMSG_VOICE_SESSION_ADJUST_PRIORITY",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A1*/ { "CMSG_VOICE_SET_TALKER_MUTED_REQUEST",STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3A2*/ { "SMSG_VOICE_SET_TALKER_MUTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A3*/ { "SMSG_INIT_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A4*/ { "SMSG_SET_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A5*/ { "SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A6*/ { "SMSG_CLEAR_EXTRA_AURA_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3A7*/ { "MSG_MOVE_START_DESCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, - /*0x3A8*/ { "CMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3A9*/ { "SMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3AA*/ { "SMSG_SPELL_CHANCE_PROC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3AB*/ { "CMSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3AC*/ { "SMSG_DISMOUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, &WorldSession::HandleVoiceSettingsOpcode }, - /*0x3B0*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B1*/ { "CMSG_GM_WHISPER", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B2*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B3*/ { "MSG_GM_GEARRATING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B4*/ { "CMSG_COMMENTATOR_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B5*/ { "SMSG_COMMENTATOR_STATE_CHANGED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B6*/ { "CMSG_COMMENTATOR_GET_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B7*/ { "SMSG_COMMENTATOR_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3B8*/ { "CMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3B9*/ { "SMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3BA*/ { "SMSG_COMMENTATOR_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3BB*/ { "CMSG_COMMENTATOR_ENTER_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3BC*/ { "CMSG_COMMENTATOR_EXIT_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3BD*/ { "CMSG_COMMENTATOR_INSTANCE_COMMAND",STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3BE*/ { "SMSG_CLEAR_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3BF*/ { "CMSG_BOT_DETECTED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3C0*/ { "SMSG_CROSSED_INEBRIATION_THRESHOLD",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C1*/ { "CMSG_CHEAT_PLAYER_LOGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3C2*/ { "CMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3C3*/ { "SMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C4*/ { "SMSG_KICK_REASON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C5*/ { "MSG_RAID_READY_CHECK_FINISHED", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckFinishOpcode}, - /*0x3C6*/ { "CMSG_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleReportSpamOpcode }, - /*0x3C7*/ { "SMSG_COMPLAIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C8*/ { "SMSG_FEATURE_SYSTEM_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3C9*/ { "CMSG_GM_SHOW_COMPLAINTS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CA*/ { "CMSG_GM_UNSQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CB*/ { "CMSG_CHANNEL_SILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CC*/ { "CMSG_CHANNEL_SILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CD*/ { "CMSG_CHANNEL_UNSILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CE*/ { "CMSG_CHANNEL_UNSILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3CF*/ { "CMSG_TARGET_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D0*/ { "CMSG_TARGET_SCRIPT_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D1*/ { "CMSG_CHANNEL_DISPLAY_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelRosterQuery }, - /*0x3D2*/ { "CMSG_SET_ACTIVE_VOICE_CHANNEL", STATUS_AUTHED, &WorldSession::HandleChannelVoiceChatQuery }, - /*0x3D3*/ { "CMSG_GET_CHANNEL_MEMBER_COUNT", STATUS_LOGGEDIN, &WorldSession::HandleChannelInfoQuery }, - /*0x3D4*/ { "SMSG_CHANNEL_MEMBER_COUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3D5*/ { "CMSG_CHANNEL_VOICE_ON", STATUS_LOGGEDIN, &WorldSession::HandleChannelEnableVoiceOpcode }, - /*0x3D6*/ { "CMSG_CHANNEL_VOICE_OFF", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D7*/ { "CMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3D8*/ { "SMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3D9*/ { "SMSG_AVAILABLE_VOICE_CHANNEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3DA*/ { "CMSG_ADD_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DB*/ { "CMSG_DEL_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DC*/ { "CMSG_PARTY_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DD*/ { "CMSG_PARTY_UNSILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DE*/ { "MSG_NOTIFY_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3DF*/ { "SMSG_COMSAT_RECONNECT_TRY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E0*/ { "SMSG_COMSAT_DISCONNECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E1*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E2*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E3*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundReportAFK }, - /*0x3E4*/ { "CMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3E5*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankQuery }, - /*0x3E6*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabColon }, - /*0x3E7*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3E8*/ { "CMSG_GUILD_BANK_SWAP_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDepositItem }, - /*0x3E9*/ { "CMSG_GUILD_BANK_BUY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankBuyTab }, - /*0x3EA*/ { "CMSG_GUILD_BANK_UPDATE_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankModifyTab }, - /*0x3EB*/ { "CMSG_GUILD_BANK_DEPOSIT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDeposit }, - /*0x3EC*/ { "CMSG_GUILD_BANK_WITHDRAW_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankWithdraw }, - /*0x3ED*/ { "MSG_GUILD_BANK_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankLog }, - /*0x3EE*/ { "CMSG_SET_CHANNEL_WATCH", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoinNotify }, - /*0x3EF*/ { "SMSG_USERLIST_ADD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F0*/ { "SMSG_USERLIST_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F1*/ { "SMSG_USERLIST_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F2*/ { "CMSG_CLEAR_CHANNEL_WATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3F3*/ { "SMSG_INSPECT_TALENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F4*/ { "SMSG_GOGOGO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F5*/ { "SMSG_ECHO_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F6*/ { "CMSG_SET_TITLE_SUFFIX", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3F7*/ { "CMSG_SPELLCLICK", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3F8*/ { "SMSG_LOOT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3F9*/ { "CMSG_GM_CHARACTER_RESTORE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3FA*/ { "CMSG_GM_CHARACTER_SAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x3FB*/ { "SMSG_VOICESESSION_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x3FC*/ { "MSG_GUILD_PERMISSIONS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetRights }, - /*0x3FD*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetMoneyAmount }, - /*0x3FE*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildEventLogOpcode }, - /*0x3FF*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x400*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x401*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x402*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x403*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK",STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x404*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT",STATUS_NEVER,&WorldSession::Handle_NULL }, - /*0x405*/ { "SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT",STATUS_NEVER,&WorldSession::Handle_ServerSide }, - /*0x406*/ { "CMSG_KEEP_ALIVE", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, - /*0x407*/ { "SMSG_RAID_READY_CHECK_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x408*/ { "CMSG_OPT_OUT_OF_LOOT", STATUS_AUTHED, &WorldSession::HandleGroupPassOnLootOpcode }, - /*0x409*/ { "MSG_QUERY_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabText }, - /*0x40A*/ { "CMSG_SET_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankSetTabText }, - /*0x40B*/ { "CMSG_SET_GRANTABLE_LEVELS", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x40C*/ { "CMSG_GRANT_LEVEL", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x40D*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x40E*/ { "MSG_GM_CHANGE_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x208*/ { "SMSG_GMTICKET_UPDATETEXT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x209*/ { "SMSG_ACCOUNT_DATA_TIMES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20A*/ { "CMSG_REQUEST_ACCOUNT_DATA", STATUS_LOGGEDIN, &WorldSession::HandleRequestAccountData }, + /*0x20B*/ { "CMSG_UPDATE_ACCOUNT_DATA", STATUS_AUTHED, &WorldSession::HandleUpdateAccountData }, + /*0x20C*/ { "SMSG_UPDATE_ACCOUNT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20D*/ { "SMSG_CLEAR_FAR_SIGHT_IMMEDIATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20E*/ { "SMSG_POWERGAINLOG_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x20F*/ { "CMSG_GM_TEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x210*/ { "CMSG_GM_CREATE_ITEM_TARGET", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x211*/ { "CMSG_GMTICKET_GETTICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketGetTicketOpcode }, + /*0x212*/ { "SMSG_GMTICKET_GETTICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x213*/ { "CMSG_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x214*/ { "SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x215*/ { "SMSG_GAMEOBJECT_DESPAWN_ANIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x216*/ { "MSG_CORPSE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleCorpseQueryOpcode }, + /*0x217*/ { "CMSG_GMTICKET_DELETETICKET", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketDeleteOpcode }, + /*0x218*/ { "SMSG_GMTICKET_DELETETICKET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x219*/ { "SMSG_CHAT_WRONG_FACTION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21A*/ { "CMSG_GMTICKET_SYSTEMSTATUS", STATUS_LOGGEDIN, &WorldSession::HandleGMTicketSystemStatusOpcode}, + /*0x21B*/ { "SMSG_GMTICKET_SYSTEMSTATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21C*/ { "CMSG_SPIRIT_HEALER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleSpiritHealerActivateOpcode}, + /*0x21D*/ { "CMSG_SET_STAT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x21E*/ { "SMSG_SET_REST_START_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x21F*/ { "CMSG_SKILL_BUY_STEP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x220*/ { "CMSG_SKILL_BUY_RANK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x221*/ { "CMSG_XP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x222*/ { "SMSG_SPIRIT_HEALER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x223*/ { "CMSG_CHARACTER_POINT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x224*/ { "SMSG_GOSSIP_POI", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x225*/ { "CMSG_CHAT_IGNORED", STATUS_LOGGEDIN, &WorldSession::HandleChatIgnoredOpcode }, + /*0x226*/ { "CMSG_GM_VISION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x227*/ { "CMSG_SERVER_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x228*/ { "CMSG_GM_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x229*/ { "CMSG_GM_REVEALTO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22A*/ { "CMSG_GM_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22B*/ { "CMSG_GM_SUMMONMOB", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22C*/ { "CMSG_GM_MOVECORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22D*/ { "CMSG_GM_FREEZE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22E*/ { "CMSG_GM_UBERINVIS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x22F*/ { "CMSG_GM_REQUEST_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x230*/ { "SMSG_GM_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x231*/ { "CMSG_GUILD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildRankOpcode }, + /*0x232*/ { "CMSG_GUILD_ADD_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildAddRankOpcode }, + /*0x233*/ { "CMSG_GUILD_DEL_RANK", STATUS_LOGGEDIN, &WorldSession::HandleGuildDelRankOpcode }, + /*0x234*/ { "CMSG_GUILD_SET_PUBLIC_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetPublicNoteOpcode }, + /*0x235*/ { "CMSG_GUILD_SET_OFFICER_NOTE", STATUS_LOGGEDIN, &WorldSession::HandleGuildSetOfficerNoteOpcode }, + /*0x236*/ { "SMSG_LOGIN_VERIFY_WORLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x237*/ { "CMSG_CLEAR_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x238*/ { "CMSG_SEND_MAIL", STATUS_LOGGEDIN, &WorldSession::HandleSendMail }, + /*0x239*/ { "SMSG_SEND_MAIL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23A*/ { "CMSG_GET_MAIL_LIST", STATUS_LOGGEDIN, &WorldSession::HandleGetMail }, + /*0x23B*/ { "SMSG_MAIL_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23C*/ { "CMSG_BATTLEFIELD_LIST", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundListOpcode }, + /*0x23D*/ { "SMSG_BATTLEFIELD_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x23E*/ { "CMSG_BATTLEFIELD_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x23F*/ { "SMSG_BATTLEFIELD_WIN_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x240*/ { "SMSG_BATTLEFIELD_LOSE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x241*/ { "CMSG_TAXICLEARNODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x242*/ { "CMSG_TAXIENABLENODE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x243*/ { "CMSG_ITEM_TEXT_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemTextQuery }, + /*0x244*/ { "SMSG_ITEM_TEXT_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x245*/ { "CMSG_MAIL_TAKE_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleTakeMoney }, + /*0x246*/ { "CMSG_MAIL_TAKE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleTakeItem }, + /*0x247*/ { "CMSG_MAIL_MARK_AS_READ", STATUS_LOGGEDIN, &WorldSession::HandleMarkAsRead }, + /*0x248*/ { "CMSG_MAIL_RETURN_TO_SENDER", STATUS_LOGGEDIN, &WorldSession::HandleReturnToSender }, + /*0x249*/ { "CMSG_MAIL_DELETE", STATUS_LOGGEDIN, &WorldSession::HandleMailDelete }, + /*0x24A*/ { "CMSG_MAIL_CREATE_TEXT_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleMailCreateTextItem }, + /*0x24B*/ { "SMSG_SPELLLOGMISS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24C*/ { "SMSG_SPELLLOGEXECUTE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24D*/ { "SMSG_DEBUGAURAPROC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24E*/ { "SMSG_PERIODICAURALOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x24F*/ { "SMSG_SPELLDAMAGESHIELD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x250*/ { "SMSG_SPELLNONMELEEDAMAGELOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x251*/ { "CMSG_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandleLearnTalentOpcode }, + /*0x252*/ { "SMSG_RESURRECT_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x253*/ { "CMSG_TOGGLE_PVP", STATUS_LOGGEDIN, &WorldSession::HandleTogglePvP }, + /*0x254*/ { "SMSG_ZONE_UNDER_ATTACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x255*/ { "MSG_AUCTION_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleAuctionHelloOpcode }, + /*0x256*/ { "CMSG_AUCTION_SELL_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionSellItem }, + /*0x257*/ { "CMSG_AUCTION_REMOVE_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAuctionRemoveItem }, + /*0x258*/ { "CMSG_AUCTION_LIST_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListItems }, + /*0x259*/ { "CMSG_AUCTION_LIST_OWNER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListOwnerItems }, + /*0x25A*/ { "CMSG_AUCTION_PLACE_BID", STATUS_LOGGEDIN, &WorldSession::HandleAuctionPlaceBid }, + /*0x25B*/ { "SMSG_AUCTION_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25C*/ { "SMSG_AUCTION_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25D*/ { "SMSG_AUCTION_OWNER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25E*/ { "SMSG_AUCTION_BIDDER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x25F*/ { "SMSG_AUCTION_OWNER_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x260*/ { "SMSG_PROCRESIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x261*/ { "SMSG_STANDSTATE_CHANGE_FAILURE_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x262*/ { "SMSG_DISPEL_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x263*/ { "SMSG_SPELLORDAMAGE_IMMUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x264*/ { "CMSG_AUCTION_LIST_BIDDER_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListBidderItems }, + /*0x265*/ { "SMSG_AUCTION_BIDDER_LIST_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x266*/ { "SMSG_SET_FLAT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x267*/ { "SMSG_SET_PCT_SPELL_MODIFIER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x268*/ { "CMSG_SET_AMMO", STATUS_LOGGEDIN, &WorldSession::HandleSetAmmoOpcode }, + /*0x269*/ { "SMSG_CORPSE_RECLAIM_DELAY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x26A*/ { "CMSG_SET_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleSetActiveMoverOpcode }, + /*0x26B*/ { "CMSG_PET_CANCEL_AURA", STATUS_LOGGEDIN, &WorldSession::HandlePetCancelAuraOpcode }, + /*0x26C*/ { "CMSG_PLAYER_AI_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x26D*/ { "CMSG_CANCEL_AUTO_REPEAT_SPELL", STATUS_LOGGEDIN, &WorldSession::HandleCancelAutoRepeatSpellOpcode}, + /*0x26E*/ { "MSG_GM_ACCOUNT_ONLINE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x26F*/ { "MSG_LIST_STABLED_PETS", STATUS_LOGGEDIN, &WorldSession::HandleListStabledPetsOpcode }, + /*0x270*/ { "CMSG_STABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStablePet }, + /*0x271*/ { "CMSG_UNSTABLE_PET", STATUS_LOGGEDIN, &WorldSession::HandleUnstablePet }, + /*0x272*/ { "CMSG_BUY_STABLE_SLOT", STATUS_LOGGEDIN, &WorldSession::HandleBuyStableSlot }, + /*0x273*/ { "SMSG_STABLE_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x274*/ { "CMSG_STABLE_REVIVE_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableRevivePet }, + /*0x275*/ { "CMSG_STABLE_SWAP_PET", STATUS_LOGGEDIN, &WorldSession::HandleStableSwapPet }, + /*0x276*/ { "MSG_QUEST_PUSH_RESULT", STATUS_LOGGEDIN, &WorldSession::HandleQuestPushResult }, + /*0x277*/ { "SMSG_PLAY_MUSIC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x278*/ { "SMSG_PLAY_OBJECT_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x279*/ { "CMSG_REQUEST_PET_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestPetInfoOpcode }, + /*0x27A*/ { "CMSG_FAR_SIGHT", STATUS_LOGGEDIN, &WorldSession::HandleFarSightOpcode }, + /*0x27B*/ { "SMSG_SPELLDISPELLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x27C*/ { "SMSG_DAMAGE_CALC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x27D*/ { "CMSG_ENABLE_DAMAGE_LOG", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x27E*/ { "CMSG_GROUP_CHANGE_SUB_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleGroupChangeSubGroupOpcode }, + /*0x27F*/ { "CMSG_REQUEST_PARTY_MEMBER_STATS", STATUS_LOGGEDIN, &WorldSession::HandleRequestPartyMemberStatsOpcode}, + /*0x280*/ { "CMSG_GROUP_SWAP_SUB_GROUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x281*/ { "CMSG_RESET_FACTION_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x282*/ { "CMSG_AUTOSTORE_BANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoStoreBankItemOpcode }, + /*0x283*/ { "CMSG_AUTOBANK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleAutoBankItemOpcode }, + /*0x284*/ { "MSG_QUERY_NEXT_MAIL_TIME", STATUS_LOGGEDIN, &WorldSession::HandleMsgQueryNextMailtime }, + /*0x285*/ { "SMSG_RECEIVED_MAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x286*/ { "SMSG_RAID_GROUP_ONLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x287*/ { "CMSG_SET_DURABILITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x288*/ { "CMSG_SET_PVP_RANK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x289*/ { "CMSG_ADD_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28A*/ { "CMSG_DEL_PVP_MEDAL_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28B*/ { "CMSG_SET_PVP_TITLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x28C*/ { "SMSG_PVP_CREDIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x28D*/ { "SMSG_AUCTION_REMOVED_NOTIFICATION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x28E*/ { "CMSG_GROUP_RAID_CONVERT", STATUS_LOGGEDIN, &WorldSession::HandleRaidConvertOpcode }, + /*0x28F*/ { "CMSG_GROUP_ASSISTANT_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleGroupAssistantOpcode }, + /*0x290*/ { "CMSG_BUYBACK_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleBuybackItem }, + /*0x291*/ { "SMSG_SERVER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x292*/ { "CMSG_MEETINGSTONE_JOIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x293*/ { "CMSG_MEETINGSTONE_LEAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x294*/ { "CMSG_MEETINGSTONE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x295*/ { "SMSG_MEETINGSTONE_SETQUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x296*/ { "CMSG_MEETINGSTONE_INFO", STATUS_LOGGEDIN, &WorldSession::HandleMeetingStoneInfo }, + /*0x297*/ { "SMSG_MEETINGSTONE_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x298*/ { "SMSG_MEETINGSTONE_IN_PROGRESS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x299*/ { "SMSG_MEETINGSTONE_MEMBER_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29A*/ { "CMSG_GMTICKETSYSTEM_TOGGLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x29B*/ { "CMSG_CANCEL_GROWTH_AURA", STATUS_LOGGEDIN, &WorldSession::HandleCancelGrowthAuraOpcode }, + /*0x29C*/ { "SMSG_CANCEL_AUTO_REPEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29D*/ { "SMSG_STANDSTATE_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29E*/ { "SMSG_LOOT_ALL_PASSED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x29F*/ { "SMSG_LOOT_ROLL_WON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A0*/ { "CMSG_LOOT_ROLL", STATUS_LOGGEDIN, &WorldSession::HandleLootRoll }, + /*0x2A1*/ { "SMSG_LOOT_START_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A2*/ { "SMSG_LOOT_ROLL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A3*/ { "CMSG_LOOT_MASTER_GIVE", STATUS_LOGGEDIN, &WorldSession::HandleLootMasterGiveOpcode }, + /*0x2A4*/ { "SMSG_LOOT_MASTER_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A5*/ { "SMSG_SET_FORCED_REACTIONS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A6*/ { "SMSG_SPELL_FAILED_OTHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A7*/ { "SMSG_GAMEOBJECT_RESET_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2A8*/ { "CMSG_REPAIR_ITEM", STATUS_LOGGEDIN, &WorldSession::HandleRepairItemOpcode }, + /*0x2A9*/ { "SMSG_CHAT_PLAYER_NOT_FOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AA*/ { "MSG_TALENT_WIPE_CONFIRM", STATUS_LOGGEDIN, &WorldSession::HandleTalentWipeOpcode }, + /*0x2AB*/ { "SMSG_SUMMON_REQUEST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AC*/ { "CMSG_SUMMON_RESPONSE", STATUS_LOGGEDIN, &WorldSession::HandleSummonResponseOpcode }, + /*0x2AD*/ { "MSG_MOVE_TOGGLE_GRAVITY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2AE*/ { "SMSG_MONSTER_MOVE_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2AF*/ { "SMSG_PET_BROKEN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B0*/ { "MSG_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B1*/ { "MSG_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B2*/ { "CMSG_SERVER_BROADCAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B3*/ { "CMSG_SELF_RES", STATUS_LOGGEDIN, &WorldSession::HandleSelfResOpcode }, + /*0x2B4*/ { "SMSG_FEIGN_DEATH_RESISTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B5*/ { "CMSG_RUN_SCRIPT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2B6*/ { "SMSG_SCRIPT_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B7*/ { "SMSG_DUEL_COUNTDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B8*/ { "SMSG_AREA_TRIGGER_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2B9*/ { "CMSG_SHOWING_HELM", STATUS_LOGGEDIN, &WorldSession::HandleToggleHelmOpcode }, + /*0x2BA*/ { "CMSG_SHOWING_CLOAK", STATUS_LOGGEDIN, &WorldSession::HandleToggleCloakOpcode }, + /*0x2BB*/ { "SMSG_MEETINGSTONE_JOINFAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BC*/ { "SMSG_PLAYER_SKINNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BD*/ { "SMSG_DURABILITY_DAMAGE_DEATH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2BE*/ { "CMSG_SET_EXPLORATION", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2BF*/ { "CMSG_SET_ACTIONBAR_TOGGLES", STATUS_AUTHED, &WorldSession::HandleSetActionBar }, + /*0x2C0*/ { "UMSG_DELETE_GUILD_CHARTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2C1*/ { "MSG_PETITION_RENAME", STATUS_LOGGEDIN, &WorldSession::HandlePetitionRenameOpcode }, + /*0x2C2*/ { "SMSG_INIT_WORLD_STATES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C3*/ { "SMSG_UPDATE_WORLD_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C4*/ { "CMSG_ITEM_NAME_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleItemNameQueryOpcode }, + /*0x2C5*/ { "SMSG_ITEM_NAME_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C6*/ { "SMSG_PET_ACTION_FEEDBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C7*/ { "CMSG_CHAR_RENAME", STATUS_AUTHED, &WorldSession::HandleChangePlayerNameOpcode }, + /*0x2C8*/ { "SMSG_CHAR_RENAME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2C9*/ { "CMSG_MOVE_SPLINE_DONE", STATUS_LOGGEDIN, &WorldSession::HandleTaxiNextDestinationOpcode }, + /*0x2CA*/ { "CMSG_MOVE_FALL_RESET", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x2CB*/ { "SMSG_INSTANCE_SAVE_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2CC*/ { "SMSG_RAID_INSTANCE_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2CD*/ { "CMSG_REQUEST_RAID_INFO", STATUS_LOGGEDIN, &WorldSession::HandleRequestRaidInfoOpcode }, + /*0x2CE*/ { "CMSG_MOVE_TIME_SKIPPED", STATUS_LOGGEDIN, &WorldSession::HandleMoveTimeSkippedOpcode }, + /*0x2CF*/ { "CMSG_MOVE_FEATHER_FALL_ACK", STATUS_LOGGEDIN, &WorldSession::HandleFeatherFallAck }, + /*0x2D0*/ { "CMSG_MOVE_WATER_WALK_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveWaterWalkAck }, + /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleMoveNotActiveMover }, + /*0x2D2*/ { "SMSG_PLAY_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2D3*/ { "CMSG_BATTLEFIELD_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleBattlefieldStatusOpcode }, + /*0x2D4*/ { "SMSG_BATTLEFIELD_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2D5*/ { "CMSG_BATTLEFIELD_PORT", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPortOpcode}, + /*0x2D6*/ { "MSG_INSPECT_HONOR_STATS", STATUS_LOGGEDIN, &WorldSession::HandleInspectHonorStatsOpcode }, + /*0x2D7*/ { "CMSG_BATTLEMASTER_HELLO", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundHelloOpcode }, + /*0x2D8*/ { "CMSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2D9*/ { "CMSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2DA*/ { "SMSG_FORCE_WALK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DB*/ { "CMSG_FORCE_WALK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x2DC*/ { "SMSG_FORCE_SWIM_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DD*/ { "CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x2DE*/ { "SMSG_FORCE_TURN_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2DF*/ { "CMSG_FORCE_TURN_RATE_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x2E0*/ { "MSG_PVP_LOG_DATA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPVPlogdataOpcode}, + /*0x2E1*/ { "CMSG_LEAVE_BATTLEFIELD", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundLeaveOpcode }, + /*0x2E2*/ { "CMSG_AREA_SPIRIT_HEALER_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueryOpcode}, + /*0x2E3*/ { "CMSG_AREA_SPIRIT_HEALER_QUEUE", STATUS_LOGGEDIN, &WorldSession::HandleAreaSpiritHealerQueueOpcode}, + /*0x2E4*/ { "SMSG_AREA_SPIRIT_HEALER_TIME", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E5*/ { "CMSG_GM_UNTEACH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2E6*/ { "SMSG_WARDEN_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E7*/ { "CMSG_WARDEN_DATA", STATUS_LOGGEDIN, &WorldSession::HandleWardenDataOpcode }, + /*0x2E8*/ { "SMSG_GROUP_JOINED_BATTLEGROUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2E9*/ { "MSG_BATTLEGROUND_PLAYER_POSITIONS", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundPlayerPositionsOpcode}, + /*0x2EA*/ { "CMSG_PET_STOP_ATTACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2EB*/ { "SMSG_BINDER_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2EC*/ { "SMSG_BATTLEGROUND_PLAYER_JOINED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2ED*/ { "SMSG_BATTLEGROUND_PLAYER_LEFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2EE*/ { "CMSG_BATTLEMASTER_JOIN", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundJoinOpcode }, + /*0x2EF*/ { "SMSG_ADDON_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F0*/ { "CMSG_PET_UNLEARN", STATUS_LOGGEDIN, &WorldSession::HandlePetUnlearnOpcode }, + /*0x2F1*/ { "SMSG_PET_UNLEARN_CONFIRM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F2*/ { "SMSG_PARTY_MEMBER_STATS_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F3*/ { "CMSG_PET_SPELL_AUTOCAST", STATUS_LOGGEDIN, &WorldSession::HandlePetSpellAutocastOpcode }, + /*0x2F4*/ { "SMSG_WEATHER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F5*/ { "SMSG_PLAY_TIME_WARNING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F6*/ { "SMSG_MINIGAME_SETUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F7*/ { "SMSG_MINIGAME_STATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2F8*/ { "CMSG_MINIGAME_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x2F9*/ { "SMSG_MINIGAME_MOVE_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FA*/ { "SMSG_RAID_INSTANCE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FB*/ { "SMSG_COMPRESSED_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FC*/ { "CMSG_GUILD_INFO_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildChangeInfoOpcode }, + /*0x2FD*/ { "SMSG_CHAT_RESTRICTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FE*/ { "SMSG_SPLINE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x2FF*/ { "SMSG_SPLINE_SET_RUN_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x300*/ { "SMSG_SPLINE_SET_SWIM_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x301*/ { "SMSG_SPLINE_SET_WALK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x302*/ { "SMSG_SPLINE_SET_SWIM_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x303*/ { "SMSG_SPLINE_SET_TURN_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x304*/ { "SMSG_SPLINE_MOVE_UNROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x305*/ { "SMSG_SPLINE_MOVE_FEATHER_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x306*/ { "SMSG_SPLINE_MOVE_NORMAL_FALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x307*/ { "SMSG_SPLINE_MOVE_SET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x308*/ { "SMSG_SPLINE_MOVE_UNSET_HOVER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x309*/ { "SMSG_SPLINE_MOVE_WATER_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30A*/ { "SMSG_SPLINE_MOVE_LAND_WALK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30B*/ { "SMSG_SPLINE_MOVE_START_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30C*/ { "SMSG_SPLINE_MOVE_STOP_SWIM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30D*/ { "SMSG_SPLINE_MOVE_SET_RUN_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30E*/ { "SMSG_SPLINE_MOVE_SET_WALK_MODE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x30F*/ { "CMSG_GM_NUKE_ACCOUNT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x310*/ { "MSG_GM_DESTROY_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x311*/ { "CMSG_GM_DESTROY_ONLINE_CORPSE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x312*/ { "CMSG_ACTIVATETAXIEXPRESS", STATUS_LOGGEDIN, &WorldSession::HandleActivateTaxiFarOpcode }, + /*0x313*/ { "SMSG_SET_FACTION_ATWAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x314*/ { "SMSG_GAMETIMEBIAS_SET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x315*/ { "CMSG_DEBUG_ACTIONS_START", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x316*/ { "CMSG_DEBUG_ACTIONS_STOP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x317*/ { "CMSG_SET_FACTION_INACTIVE", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionInactiveOpcode}, + /*0x318*/ { "CMSG_SET_WATCHED_FACTION", STATUS_LOGGEDIN, &WorldSession::HandleSetWatchedFactionIndexOpcode}, + /*0x319*/ { "MSG_MOVE_TIME_SKIPPED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x31A*/ { "SMSG_SPLINE_MOVE_ROOT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31B*/ { "CMSG_SET_EXPLORATION_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x31C*/ { "SMSG_INVALIDATE_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31D*/ { "CMSG_RESET_INSTANCES", STATUS_LOGGEDIN, &WorldSession::HandleResetInstancesOpcode }, + /*0x31E*/ { "SMSG_INSTANCE_RESET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x31F*/ { "SMSG_INSTANCE_RESET_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x320*/ { "SMSG_UPDATE_LAST_INSTANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x321*/ { "MSG_RAID_TARGET_UPDATE", STATUS_LOGGEDIN, &WorldSession::HandleRaidIconTargetOpcode }, + /*0x322*/ { "MSG_RAID_READY_CHECK", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckOpcode }, + /*0x323*/ { "CMSG_LUA_USAGE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x324*/ { "SMSG_PET_ACTION_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x325*/ { "SMSG_PET_DISMISS_SOUND", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x326*/ { "SMSG_GHOSTEE_GONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x327*/ { "CMSG_GM_UPDATE_TICKET_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x328*/ { "SMSG_GM_TICKET_STATUS_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x329*/ { "MSG_SET_DUNGEON_DIFFICULTY", STATUS_LOGGEDIN, &WorldSession::HandleDungeonDifficultyOpcode }, + /*0x32A*/ { "CMSG_GMSURVEY_SUBMIT", STATUS_NEVER, &WorldSession::Handle_NULL },//LOGGEDIN, &WorldSession::HandleGMSurveySubmit }, + /*0x32B*/ { "SMSG_UPDATE_INSTANCE_OWNERSHIP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x32C*/ { "CMSG_IGNORE_KNOCKBACK_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x32D*/ { "SMSG_CHAT_PLAYER_AMBIGUOUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x32E*/ { "MSG_DELAY_GHOST_TELEPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x32F*/ { "SMSG_SPELLINSTAKILLLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x330*/ { "SMSG_SPELL_UPDATE_CHAIN_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x331*/ { "CMSG_CHAT_FILTERED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x332*/ { "SMSG_EXPECTED_SPAM_RECORDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x333*/ { "SMSG_SPELLSTEALLOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x334*/ { "CMSG_LOTTERY_QUERY_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x335*/ { "SMSG_LOTTERY_QUERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x336*/ { "CMSG_BUY_LOTTERY_TICKET_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x337*/ { "SMSG_LOTTERY_RESULT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x338*/ { "SMSG_CHARACTER_PROFILE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x339*/ { "SMSG_CHARACTER_PROFILE_REALM_CONNECTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33A*/ { "SMSG_DEFENSE_MESSAGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33B*/ { "SMSG_INSTANCE_DIFFICULTY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33C*/ { "MSG_GM_RESETINSTANCELIMIT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x33D*/ { "SMSG_MOTD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33E*/ { "SMSG_MOVE_SET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x33F*/ { "SMSG_MOVE_UNSET_FLIGHT_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x340*/ { "CMSG_MOVE_FLIGHT_ACK_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x341*/ { "MSG_MOVE_START_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x342*/ { "MSG_MOVE_STOP_SWIM_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x343*/ { "SMSG_MOVE_SET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x344*/ { "SMSG_MOVE_UNSET_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x345*/ { "CMSG_MOVE_SET_CAN_FLY_ACK", STATUS_LOGGEDIN, &WorldSession::HandleMoveFlyModeChangeAckOpcode}, + /*0x346*/ { "CMSG_MOVE_SET_FLY", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x347*/ { "CMSG_SOCKET_GEMS", STATUS_LOGGEDIN, &WorldSession::HandleSocketOpcode }, + /*0x348*/ { "CMSG_ARENA_TEAM_CREATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x349*/ { "SMSG_ARENA_TEAM_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34A*/ { "UMSG_UPDATE_ARENA_TEAM_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x34B*/ { "CMSG_ARENA_TEAM_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamQueryOpcode }, + /*0x34C*/ { "SMSG_ARENA_TEAM_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34D*/ { "CMSG_ARENA_TEAM_ROSTER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRosterOpcode }, + /*0x34E*/ { "SMSG_ARENA_TEAM_ROSTER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x34F*/ { "CMSG_ARENA_TEAM_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamAddMemberOpcode }, + /*0x350*/ { "SMSG_ARENA_TEAM_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x351*/ { "CMSG_ARENA_TEAM_ACCEPT", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteAcceptOpcode}, + /*0x352*/ { "CMSG_ARENA_TEAM_DECLINE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamInviteDeclineOpcode}, + /*0x353*/ { "CMSG_ARENA_TEAM_LEAVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamLeaveOpcode }, + /*0x354*/ { "CMSG_ARENA_TEAM_REMOVE", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamRemoveFromTeamOpcode}, + /*0x355*/ { "CMSG_ARENA_TEAM_DISBAND", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamDisbandOpcode }, + /*0x356*/ { "CMSG_ARENA_TEAM_LEADER", STATUS_LOGGEDIN, &WorldSession::HandleArenaTeamPromoteToCaptainOpcode}, + /*0x357*/ { "SMSG_ARENA_TEAM_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x358*/ { "CMSG_BATTLEMASTER_JOIN_ARENA", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundArenaJoin }, + /*0x359*/ { "MSG_MOVE_START_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x35A*/ { "MSG_MOVE_STOP_ASCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x35B*/ { "SMSG_ARENA_TEAM_STATS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x35C*/ { "CMSG_LFG_SET_AUTOJOIN", STATUS_AUTHED, &WorldSession::HandleLfgAutoJoinOpcode }, + /*0x35D*/ { "CMSG_LFG_CLEAR_AUTOJOIN", STATUS_LOGGEDIN, &WorldSession::HandleLfgCancelAutoJoinOpcode }, + /*0x35E*/ { "CMSG_LFM_SET_AUTOFILL", STATUS_AUTHED, &WorldSession::HandleLfmAutoAddMembersOpcode }, + /*0x35F*/ { "CMSG_LFM_CLEAR_AUTOFILL", STATUS_LOGGEDIN, &WorldSession::HandleLfmCancelAutoAddmembersOpcode}, + /*0x360*/ { "CMSG_ACCEPT_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x361*/ { "CMSG_DECLINE_LFG_MATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x362*/ { "CMSG_CANCEL_PENDING_LFG", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x363*/ { "CMSG_CLEAR_LOOKING_FOR_GROUP", STATUS_LOGGEDIN, &WorldSession::HandleLfgClearOpcode }, + /*0x364*/ { "CMSG_CLEAR_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetNoneOpcode }, + /*0x365*/ { "CMSG_SET_LOOKING_FOR_MORE", STATUS_LOGGEDIN, &WorldSession::HandleLfmSetOpcode }, + /*0x366*/ { "CMSG_SET_LFG_COMMENT", STATUS_LOGGEDIN, &WorldSession::HandleLfgSetCommentOpcode }, + /*0x367*/ { "SMSG_LFG_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x368*/ { "SMSG_LFG_OTHER_TIMEDOUT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x369*/ { "SMSG_LFG_AUTOJOIN_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36A*/ { "SMSG_LFG_AUTOJOIN_FAILED_NO_PLAYER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36B*/ { "SMSG_LFG_LEADER_IS_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36C*/ { "SMSG_LFG_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36D*/ { "SMSG_LFG_UPDATE_LFM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36E*/ { "SMSG_LFG_UPDATE_LFG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x36F*/ { "SMSG_LFG_UPDATE_QUEUED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x370*/ { "SMSG_LFG_PENDING_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x371*/ { "SMSG_LFG_PENDING_MATCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x372*/ { "SMSG_LFG_PENDING_MATCH_DONE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x373*/ { "SMSG_TITLE_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x374*/ { "CMSG_SET_TITLE", STATUS_LOGGEDIN, &WorldSession::HandleChooseTitleOpcode }, + /*0x375*/ { "CMSG_CANCEL_MOUNT_AURA", STATUS_LOGGEDIN, &WorldSession::HandleDismountOpcode }, + /*0x376*/ { "SMSG_ARENA_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x377*/ { "MSG_INSPECT_ARENA_TEAMS", STATUS_LOGGEDIN, &WorldSession::HandleInspectArenaStatsOpcode }, + /*0x378*/ { "SMSG_DEATH_RELEASE_LOC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x379*/ { "CMSG_CANCEL_TEMP_ENCHANTMENT", STATUS_LOGGEDIN, &WorldSession::HandleCancelTempItemEnchantmentOpcode}, + /*0x37A*/ { "SMSG_FORCED_DEATH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x37B*/ { "CMSG_CHEAT_SET_HONOR_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37C*/ { "CMSG_CHEAT_SET_ARENA_CURRENCY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37D*/ { "MSG_MOVE_SET_FLIGHT_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37E*/ { "MSG_MOVE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x37F*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x380*/ { "MSG_MOVE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x381*/ { "SMSG_FORCE_FLIGHT_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x382*/ { "CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x383*/ { "SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x384*/ { "CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK", STATUS_LOGGEDIN, &WorldSession::HandleForceSpeedChangeAck }, + /*0x385*/ { "SMSG_SPLINE_SET_FLIGHT_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x386*/ { "SMSG_SPLINE_SET_FLIGHT_BACK_SPEED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x387*/ { "CMSG_MAELSTROM_INVALIDATE_CACHE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x388*/ { "SMSG_FLIGHT_SPLINE_SYNC", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x389*/ { "CMSG_SET_TAXI_BENCHMARK_MODE", STATUS_AUTHED, &WorldSession::HandleSetTaxiBenchmarkOpcode }, + /*0x38A*/ { "SMSG_JOINED_BATTLEGROUND_QUEUE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x38B*/ { "SMSG_REALM_SPLIT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x38C*/ { "CMSG_REALM_SPLIT", STATUS_AUTHED, &WorldSession::HandleRealmStateRequestOpcode }, + /*0x38D*/ { "CMSG_MOVE_CHNG_TRANSPORT", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x38E*/ { "MSG_PARTY_ASSIGNMENT", STATUS_LOGGEDIN, &WorldSession::HandleGroupPromoteOpcode }, + /*0x38F*/ { "SMSG_OFFER_PETITION_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x390*/ { "SMSG_TIME_SYNC_REQ", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x391*/ { "CMSG_TIME_SYNC_RESP", STATUS_LOGGEDIN, &WorldSession::HandleTimeSyncResp }, + /*0x392*/ { "CMSG_SEND_LOCAL_EVENT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x393*/ { "CMSG_SEND_GENERAL_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x394*/ { "CMSG_SEND_COMBAT_TRIGGER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x395*/ { "CMSG_MAELSTROM_GM_SENT_MAIL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x396*/ { "SMSG_RESET_FAILED_NOTIFY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x397*/ { "SMSG_REAL_GROUP_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x398*/ { "SMSG_LFG_DISABLED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x399*/ { "CMSG_ACTIVE_PVP_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x39A*/ { "CMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x39B*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x39C*/ { "SMSG_CHEAT_DUMP_ITEMS_DEBUG_ONLY_RESPONSE_WRITE_FILE",STATUS_NEVER,&WorldSession::Handle_ServerSide }, + /*0x39D*/ { "SMSG_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x39E*/ { "SMSG_VOICE_SESSION_ROSTER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x39F*/ { "SMSG_VOICE_SESSION_LEAVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A0*/ { "SMSG_VOICE_SESSION_ADJUST_PRIORITY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A1*/ { "CMSG_VOICE_SET_TALKER_MUTED_REQUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3A2*/ { "SMSG_VOICE_SET_TALKER_MUTED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A3*/ { "SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A4*/ { "SMSG_SET_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A5*/ { "SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE",STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A6*/ { "SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3A7*/ { "MSG_MOVE_START_DESCEND", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, + /*0x3A8*/ { "CMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3A9*/ { "SMSG_IGNORE_REQUIREMENTS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AA*/ { "SMSG_SPELL_CHANCE_PROC_LOG", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AB*/ { "CMSG_MOVE_SET_RUN_SPEED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AC*/ { "SMSG_DISMOUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, &WorldSession::HandleVoiceSettingsOpcode }, + /*0x3B0*/ { "SMSG_VOICE_SESSION_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B1*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B2*/ { "CMSG_GM_WHISPER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B3*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B4*/ { "MSG_GM_GEARRATING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B5*/ { "CMSG_COMMENTATOR_ENABLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B6*/ { "SMSG_COMMENTATOR_STATE_CHANGED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B7*/ { "CMSG_COMMENTATOR_GET_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3B8*/ { "SMSG_COMMENTATOR_MAP_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3B9*/ { "CMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BA*/ { "SMSG_COMMENTATOR_GET_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3BB*/ { "SMSG_COMMENTATOR_PLAYER_INFO", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3BC*/ { "CMSG_COMMENTATOR_ENTER_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BD*/ { "CMSG_COMMENTATOR_EXIT_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BE*/ { "CMSG_COMMENTATOR_INSTANCE_COMMAND", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3BF*/ { "SMSG_CLEAR_TARGET", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C0*/ { "CMSG_BOT_DETECTED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C1*/ { "SMSG_CROSSED_INEBRIATION_THRESHOLD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C2*/ { "CMSG_CHEAT_PLAYER_LOGIN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C3*/ { "CMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3C4*/ { "SMSG_CHEAT_PLAYER_LOOKUP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C5*/ { "SMSG_KICK_REASON", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C6*/ { "MSG_RAID_READY_CHECK_FINISHED", STATUS_LOGGEDIN, &WorldSession::HandleRaidReadyCheckFinishOpcode}, + /*0x3C7*/ { "CMSG_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleReportSpamOpcode }, + /*0x3C8*/ { "SMSG_COMPLAIN_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3C9*/ { "SMSG_FEATURE_SYSTEM_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3CA*/ { "CMSG_GM_SHOW_COMPLAINTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CB*/ { "CMSG_GM_UNSQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CC*/ { "CMSG_CHANNEL_SILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CD*/ { "CMSG_CHANNEL_SILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CE*/ { "CMSG_CHANNEL_UNSILENCE_VOICE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3CF*/ { "CMSG_CHANNEL_UNSILENCE_ALL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D0*/ { "CMSG_TARGET_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D1*/ { "CMSG_TARGET_SCRIPT_CAST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D2*/ { "CMSG_CHANNEL_DISPLAY_LIST", STATUS_LOGGEDIN, &WorldSession::HandleChannelRosterQuery }, + /*0x3D3*/ { "CMSG_SET_ACTIVE_VOICE_CHANNEL", STATUS_AUTHED, &WorldSession::HandleChannelVoiceChatQuery }, + /*0x3D4*/ { "CMSG_GET_CHANNEL_MEMBER_COUNT", STATUS_LOGGEDIN, &WorldSession::HandleChannelInfoQuery }, + /*0x3D5*/ { "SMSG_CHANNEL_MEMBER_COUNT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3D6*/ { "CMSG_CHANNEL_VOICE_ON", STATUS_LOGGEDIN, &WorldSession::HandleChannelEnableVoiceOpcode }, + /*0x3D7*/ { "CMSG_CHANNEL_VOICE_OFF", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D8*/ { "CMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3D9*/ { "SMSG_DEBUG_LIST_TARGETS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3DA*/ { "SMSG_AVAILABLE_VOICE_CHANNEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3DB*/ { "CMSG_ADD_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DC*/ { "CMSG_DEL_VOICE_IGNORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DD*/ { "CMSG_PARTY_SILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DE*/ { "CMSG_PARTY_UNSILENCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3DF*/ { "MSG_NOTIFY_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3E0*/ { "SMSG_COMSAT_RECONNECT_TRY", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E1*/ { "SMSG_COMSAT_DISCONNECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E2*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E3*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E4*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, &WorldSession::HandleBattleGroundReportAFK }, + /*0x3E5*/ { "CMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3E6*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankQuery }, + /*0x3E7*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabColon }, + /*0x3E8*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3E9*/ { "CMSG_GUILD_BANK_SWAP_ITEMS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDepositItem }, + /*0x3EA*/ { "CMSG_GUILD_BANK_BUY_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankBuyTab }, + /*0x3EB*/ { "CMSG_GUILD_BANK_UPDATE_TAB", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankModifyTab }, + /*0x3EC*/ { "CMSG_GUILD_BANK_DEPOSIT_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankDeposit }, + /*0x3ED*/ { "CMSG_GUILD_BANK_WITHDRAW_MONEY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankWithdraw }, + /*0x3EE*/ { "MSG_GUILD_BANK_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankLog }, + /*0x3EF*/ { "CMSG_SET_CHANNEL_WATCH", STATUS_LOGGEDIN, &WorldSession::HandleChannelJoinNotify }, + /*0x3F0*/ { "SMSG_USERLIST_ADD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F1*/ { "SMSG_USERLIST_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F2*/ { "SMSG_USERLIST_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F3*/ { "CMSG_CLEAR_CHANNEL_WATCH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3F4*/ { "SMSG_INSPECT_TALENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F5*/ { "SMSG_GOGOGO_OBSOLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F6*/ { "SMSG_ECHO_PARTY_SQUELCH", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3F7*/ { "CMSG_SET_TITLE_SUFFIX", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3F8*/ { "CMSG_SPELLCLICK", STATUS_LOGGEDIN, &WorldSession::HandleSpellClick }, + /*0x3F9*/ { "SMSG_LOOT_LIST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3FA*/ { "CMSG_GM_CHARACTER_RESTORE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3FB*/ { "CMSG_GM_CHARACTER_SAVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x3FC*/ { "SMSG_VOICESESSION_FULL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x3FD*/ { "MSG_GUILD_PERMISSIONS", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetRights }, + /*0x3FE*/ { "MSG_GUILD_BANK_MONEY_WITHDRAWN", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankGetMoneyAmount }, + /*0x3FF*/ { "MSG_GUILD_EVENT_LOG_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleGuildEventLogOpcode }, + /*0x400*/ { "CMSG_MAELSTROM_RENAME_GUILD", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x401*/ { "CMSG_GET_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x402*/ { "SMSG_MIRRORIMAGE_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x403*/ { "SMSG_FORCE_DISPLAY_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x404*/ { "SMSG_SPELL_CHANCE_RESIST_PUSHBACK", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x405*/ { "CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x406*/ { "SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x407*/ { "CMSG_KEEP_ALIVE", STATUS_NEVER, &WorldSession::Handle_EarlyProccess }, + /*0x408*/ { "SMSG_RAID_READY_CHECK_ERROR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x409*/ { "CMSG_OPT_OUT_OF_LOOT", STATUS_AUTHED, &WorldSession::HandleGroupPassOnLootOpcode }, + /*0x40A*/ { "MSG_QUERY_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankTabText }, + /*0x40B*/ { "CMSG_SET_GUILD_BANK_TEXT", STATUS_LOGGEDIN, &WorldSession::HandleGuildBankSetTabText }, + /*0x40C*/ { "CMSG_SET_GRANTABLE_LEVELS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40D*/ { "CMSG_GRANT_LEVEL", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x40E*/ { "CMSG_REFER_A_FRIEND", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x40F*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleChannelDeclineInvite }, - /*0x410*/ { "CMSG_GROUPACTION_THROTTLED", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x411*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x412*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x413*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, &WorldSession::HandleTotemDestroy }, - /*0x414*/ { "CMSG_EXPIRE_RAID_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x415*/ { "CMSG_NO_SPELL_VARIANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x416*/ { "CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY",STATUS_LOGGEDIN,&WorldSession::HandleQuestgiverStatusQueryMultipleOpcode}, - /*0x417*/ { "SMSG_QUESTGIVER_STATUS_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x418*/ { "CMSG_SET_PLAYER_DECLINED_NAMES", STATUS_AUTHED, &WorldSession::HandleDeclinedPlayerNameOpcode }, - /*0x419*/ { "SMSG_SET_PLAYER_DECLINED_NAMES_RESULT",STATUS_NEVER,&WorldSession::Handle_ServerSide }, - /*0x41A*/ { "CMSG_QUERY_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x41B*/ { "CMSG_CLEAR_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x41C*/ { "SMSG_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x41D*/ { "SMSG_SEND_UNLEARN_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x41E*/ { "SMSG_PROPOSE_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x41F*/ { "CMSG_ACCEPT_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x420*/ { "SMSG_REFER_A_FRIEND_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x421*/ { "SMSG_SPLINE_MOVE_SET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x422*/ { "SMSG_SPLINE_MOVE_UNSET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x423*/ { "SMSG_SUMMON_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x410*/ { "CMSG_DECLINE_CHANNEL_INVITE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x411*/ { "CMSG_GROUPACTION_THROTTLED", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x412*/ { "SMSG_OVERRIDE_LIGHT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x413*/ { "SMSG_TOTEM_CREATED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x414*/ { "CMSG_TOTEM_DESTROYED", STATUS_LOGGEDIN, &WorldSession::HandleTotemDestroy }, + /*0x415*/ { "CMSG_EXPIRE_RAID_INSTANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x416*/ { "CMSG_NO_SPELL_VARIANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x417*/ { "CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY", STATUS_LOGGEDIN, &WorldSession::HandleQuestgiverStatusQueryMultipleOpcode}, + /*0x418*/ { "SMSG_QUESTGIVER_STATUS_MULTIPLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x419*/ { "CMSG_SET_PLAYER_DECLINED_NAMES", STATUS_AUTHED, &WorldSession::HandleDeclinedPlayerNameOpcode }, + /*0x41A*/ { "SMSG_SET_PLAYER_DECLINED_NAMES_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41B*/ { "CMSG_QUERY_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x41C*/ { "CMSG_CLEAR_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x41D*/ { "SMSG_SERVER_BUCK_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41E*/ { "SMSG_SEND_UNLEARN_SPELLS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x41F*/ { "SMSG_PROPOSE_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x420*/ { "CMSG_ACCEPT_LEVEL_GRANT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x421*/ { "SMSG_REFER_A_FRIEND_FAILURE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x422*/ { "SMSG_SPLINE_MOVE_SET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x423*/ { "SMSG_SPLINE_MOVE_UNSET_FLYING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x424*/ { "SMSG_SUMMON_CANCEL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x425*/ { "CMSG_CHANGE_PERSONAL_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x426*/ { "CMSG_ALTER_APPEARANCE", STATUS_LOGGEDIN, &WorldSession::HandleAlterAppearance }, + /*0x427*/ { "SMSG_ENABLE_BARBER_SHOP", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x428*/ { "SMSG_BARBER_SHOP_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x429*/ { "CMSG_CALENDAR_GET_CALENDAR", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetCalendar }, + /*0x42A*/ { "CMSG_CALENDAR_GET_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetEvent }, + /*0x42B*/ { "CMSG_CALENDAR_GUILD_FILTER", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGuildFilter }, + /*0x42C*/ { "CMSG_CALENDAR_ARENA_TEAM", STATUS_LOGGEDIN, &WorldSession::HandleCalendarArenaTeam }, + /*0x42D*/ { "CMSG_CALENDAR_ADD_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarAddEvent }, + /*0x42E*/ { "CMSG_CALENDAR_UPDATE_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarUpdateEvent }, + /*0x42F*/ { "CMSG_CALENDAR_REMOVE_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarRemoveEvent }, + /*0x430*/ { "CMSG_CALENDAR_COPY_EVENT", STATUS_LOGGEDIN, &WorldSession::HandleCalendarCopyEvent }, + /*0x431*/ { "CMSG_CALENDAR_EVENT_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventInvite }, + /*0x432*/ { "CMSG_CALENDAR_EVENT_RSVP", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventRsvp }, + /*0x433*/ { "CMSG_CALENDAR_EVENT_REMOVE_INVITE", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventRemoveInvite }, + /*0x434*/ { "CMSG_CALENDAR_EVENT_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventStatus }, + /*0x435*/ { "CMSG_CALENDAR_EVENT_MODERATOR_STATUS", STATUS_LOGGEDIN, &WorldSession::HandleCalendarEventModeratorStatus}, + /*0x436*/ { "SMSG_CALENDAR_SEND_CALENDAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x437*/ { "SMSG_CALENDAR_SEND_EVENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x438*/ { "SMSG_CALENDAR_FILTER_GUILD", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x439*/ { "SMSG_CALENDAR_ARENA_TEAM", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43A*/ { "SMSG_CALENDAR_EVENT_INVITE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43B*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43C*/ { "SMSG_CALENDAR_EVENT_STATUS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43D*/ { "SMSG_CALENDAR_COMMAND_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43E*/ { "SMSG_CALENDAR_RAID_LOCKOUT_ADDED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x43F*/ { "SMSG_CALENDAR_RAID_LOCKOUT_REMOVED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x440*/ { "SMSG_CALENDAR_EVENT_INVITE_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x441*/ { "SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x442*/ { "SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x443*/ { "SMSG_CALENDAR_EVENT_REMOVED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x444*/ { "SMSG_CALENDAR_EVENT_UPDATED_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x445*/ { "SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x446*/ { "CMSG_CALENDAR_COMPLAIN", STATUS_LOGGEDIN, &WorldSession::HandleCalendarComplain }, + /*0x447*/ { "CMSG_CALENDAR_GET_NUM_PENDING", STATUS_LOGGEDIN, &WorldSession::HandleCalendarGetNumPending }, + /*0x448*/ { "SMSG_CALENDAR_SEND_NUM_PENDING", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x449*/ { "CMSG_SAVE_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44A*/ { "SMSG_NOTIFY_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x44B*/ { "CMSG_PLAY_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44C*/ { "SMSG_PLAY_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x44D*/ { "CMSG_LOAD_DANCES", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44E*/ { "CMSG_STOP_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x44F*/ { "SMSG_STOP_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x450*/ { "CMSG_SYNC_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x451*/ { "CMSG_DANCE_QUERY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x452*/ { "SMSG_DANCE_QUERY_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x453*/ { "SMSG_INVALIDATE_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x454*/ { "CMSG_DELETE_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x455*/ { "SMSG_LEARNED_DANCE_MOVES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x456*/ { "CMSG_LEARN_DANCE_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x457*/ { "CMSG_UNLEARN_DANCE_MOVE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x458*/ { "CMSG_SET_RUNE_COUNT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x459*/ { "CMSG_SET_RUNE_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45A*/ { "MSG_MOVE_SET_PITCH_RATE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45B*/ { "MSG_MOVE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45C*/ { "SMSG_FORCE_PITCH_RATE_CHANGE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x45D*/ { "CMSG_FORCE_PITCH_RATE_CHANGE_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x45E*/ { "SMSG_SPLINE_SET_PITCH_RATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x45F*/ { "SMSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x460*/ { "MSG_MOVE_ABANDON_TRANSPORT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x461*/ { "CMSG_MOVE_ABANDON_TRANSPORT_ACK", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x464*/ { "SMSG_TRIGGER_MOVIE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x465*/ { "CMSG_COMPLETE_MOVIE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x466*/ { "CMSG_SET_GLYPH_SLOT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x467*/ { "CMSG_SET_GLYPH", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x468*/ { "SMSG_ACHIEVEMENT_EARNED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x469*/ { "SMSG_DYNAMIC_DROP_ROLL_RESULT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x46A*/ { "SMSG_CRITERIA_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x46B*/ { "CMSG_QUERY_INSPECT_ACHIEVEMENTS", STATUS_LOGGEDIN, &WorldSession::HandleInspectAchievements }, + /*0x46C*/ { "SMSG_RESPOND_INSPECT_ACHIEVEMENTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x46D*/ { "CMSG_DISMISS_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, &WorldSession::HandleDismissControlledVehicle }, + /*0x46E*/ { "CMSG_COMPLETE_ACHIEVEMENT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x46F*/ { "SMSG_QUESTUPDATE_ADD_PVP_KILL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x470*/ { "CMSG_SET_CRITERIA_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x471*/ { "SMSG_GROUP_SWAP_FAILED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x472*/ { "CMSG_UNITANIMTIER_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x473*/ { "CMSG_CHAR_CUSTOMIZE", STATUS_AUTHED, &WorldSession::HandleCharCustomize }, + /*0x474*/ { "SMSG_CHAR_CUSTOMIZE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x475*/ { "SMSG_PET_RENAMEABLE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x476*/ { "CMSG_REQUEST_VEHICLE_EXIT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x477*/ { "CMSG_REQUEST_VEHICLE_PREV_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x478*/ { "CMSG_REQUEST_VEHICLE_NEXT_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x479*/ { "CMSG_REQUEST_VEHICLE_SWITCH_SEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x47A*/ { "CMSG_PET_LEARN_TALENT", STATUS_LOGGEDIN, &WorldSession::HandlePetLearnTalent }, + /*0x47B*/ { "CMSG_PET_UNLEARN_TALENTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x47C*/ { "SMSG_SET_PHASE_SHIFT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x47D*/ { "SMSG_ALL_ACHIEVEMENT_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x47E*/ { "CMSG_FORCE_SAY_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x47F*/ { "SMSG_HEALTH_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x480*/ { "SMSG_POWER_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x481*/ { "CMSG_GAMEOBJ_REPORT_USE", STATUS_LOGGEDIN, &WorldSession::HandleGameobjectReportUse }, + /*0x482*/ { "SMSG_HIGHEST_THREAT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x483*/ { "SMSG_THREAT_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x484*/ { "SMSG_THREAT_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x485*/ { "SMSG_THREAT_CLEAR", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x486*/ { "SMSG_CONVERT_RUNE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x487*/ { "SMSG_RESYNC_RUNES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x488*/ { "SMSG_ADD_RUNE_POWER", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x489*/ { "CMSG_START_QUEST", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x48A*/ { "CMSG_REMOVE_GLYPH", STATUS_LOGGEDIN, &WorldSession::HandleRemoveGlyph }, + /*0x48B*/ { "CMSG_DUMP_OBJECTS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x48C*/ { "SMSG_DUMP_OBJECTS_DATA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x48D*/ { "CMSG_DISMISS_CRITTER", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x48E*/ { "SMSG_NOTIFY_DEST_LOC_SPELL_CAST", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x48F*/ { "CMSG_AUCTION_LIST_PENDING_SALES", STATUS_LOGGEDIN, &WorldSession::HandleAuctionListPendingSales }, + /*0x490*/ { "SMSG_AUCTION_LIST_PENDING_SALES", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x491*/ { "SMSG_MODIFY_COOLDOWN", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x492*/ { "SMSG_PET_UPDATE_COMBO_POINTS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x493*/ { "CMSG_ENABLETAXI", STATUS_LOGGEDIN, &WorldSession::HandleTaxiQueryAvailableNodes }, + /*0x494*/ { "SMSG_PRE_RESURRECT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x495*/ { "SMSG_AURA_UPDATE_ALL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x496*/ { "SMSG_AURA_UPDATE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x497*/ { "CMSG_FLOOD_GRACE_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x499*/ { "SMSG_PET_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49A*/ { "SMSG_PET_REMOVED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49B*/ { "CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x49C*/ { "CMSG_HEARTH_AND_RESURRECT", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x49D*/ { "SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49E*/ { "SMSG_CRITERIA_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49F*/ { "SMSG_ACHIEVEMENT_DELETED", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A0*/ { "CMSG_SERVER_INFO_QUERY", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A1*/ { "SMSG_SERVER_INFO_RESPONSE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A2*/ { "CMSG_CHECK_LOGIN_CRITERIA", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A3*/ { "SMSG_SERVER_BUCK_DATA_START", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A4*/ { "CMSG_QUERY_VEHICLE_STATUS", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A5*/ { "SMSG_PET_GUIDS", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A6*/ { "SMSG_CLIENTCACHE_VERSION", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x4A7*/ { "UMSG_UNKNOWN_1191", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A8*/ { "UMSG_UNKNOWN_1192", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4A9*/ { "UMSG_UNKNOWN_1193", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4AA*/ { "UMSG_UNKNOWN_1194", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4AB*/ { "UMSG_UNKNOWN_1195", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x4AC*/ { "UMSG_UNKNOWN_1196", STATUS_NEVER, &WorldSession::Handle_NULL }, }; diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 202166a57a0..2eb5d2d2920 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,8 +49,8 @@ enum Opcodes CMSG_ZONE_MAP = 0x00A, SMSG_ZONE_MAP = 0x00B, CMSG_DEBUG_CHANGECELLZONE = 0x00C, - CMSG_EMBLAZON_TABARD_OBSOLETE = 0x00D, - CMSG_UNEMBLAZON_TABARD_OBSOLETE = 0x00E, + CMSG_MOVE_CHARACTER_CHEAT = 0x00D, + SMSG_MOVE_CHARACTER_CHEAT = 0x00E, CMSG_RECHARGE = 0x00F, CMSG_LEARN_SPELL = 0x010, CMSG_CREATEMONSTER = 0x011, @@ -66,7 +66,7 @@ enum Opcodes SMSG_FORCEACTIONSHOW = 0x01B, CMSG_PETGODMODE = 0x01C, SMSG_PETGODMODE = 0x01D, - SMSG_DEBUGINFOSPELLMISS_OBSOLETE = 0x01E, + SMSG_REFER_A_FRIEND_EXPIRED = 0x01E, CMSG_WEATHER_SPEED_CHEAT = 0x01F, CMSG_UNDRESSPLAYER = 0x020, CMSG_BEASTMASTER = 0x021, @@ -86,7 +86,7 @@ enum Opcodes SMSG_DEBUG_AISTATE = 0x02F, CMSG_DISABLE_PVP_CHEAT = 0x030, CMSG_ADVANCE_SPAWN_TIME = 0x031, - CMSG_PVP_PORT_OBSOLETE = 0x032, + SMSG_DESTRUCTIBLE_BUILDING_DAMAGE = 0x032, CMSG_AUTH_SRP6_BEGIN = 0x033, CMSG_AUTH_SRP6_PROOF = 0x034, CMSG_AUTH_SRP6_RECODE = 0x035, @@ -214,7 +214,7 @@ enum Opcodes SMSG_READ_ITEM_FAILED = 0x0AF, SMSG_ITEM_COOLDOWN = 0x0B0, CMSG_GAMEOBJ_USE = 0x0B1, - CMSG_GAMEOBJ_CHAIR_USE_OBSOLETE = 0x0B2, + CMSG_DESTROY_ITEMS = 0x0B2, SMSG_GAMEOBJECT_CUSTOM_ANIM = 0x0B3, CMSG_AREATRIGGER = 0x0B4, MSG_MOVE_START_FORWARD = 0x0B5, @@ -347,7 +347,7 @@ enum Opcodes SMSG_SPELL_COOLDOWN = 0x134, SMSG_COOLDOWN_EVENT = 0x135, CMSG_CANCEL_AURA = 0x136, - SMSG_UPDATE_AURA_DURATION = 0x137, + SMSG_UPDATE_AURA_DURATION_OBSOLETE = 0x137, SMSG_PET_CAST_FAILED = 0x138, MSG_CHANNEL_START = 0x139, MSG_CHANNEL_UPDATE = 0x13A, @@ -371,10 +371,10 @@ enum Opcodes SMSG_DAMAGE_DONE_OBSOLETE = 0x14C, SMSG_DAMAGE_TAKEN_OBSOLETE = 0x14D, SMSG_CANCEL_COMBAT = 0x14E, - SMSG_PLAYER_COMBAT_XP_GAIN_OBSOLETE = 0x14F, + SMSG_SPELLBREAKLOG = 0x14F, SMSG_SPELLHEALLOG = 0x150, SMSG_SPELLENERGIZELOG = 0x151, - CMSG_SHEATHE_OBSOLETE = 0x152, + SMSG_BREAK_TARGET = 0x152, CMSG_SAVE_PLAYER = 0x153, CMSG_SETDEATHBINDPOINT = 0x154, SMSG_BINDPOINTUPDATE = 0x155, @@ -578,7 +578,7 @@ enum Opcodes SMSG_GMTICKET_SYSTEMSTATUS = 0x21B, CMSG_SPIRIT_HEALER_ACTIVATE = 0x21C, CMSG_SET_STAT_CHEAT = 0x21D, - SMSG_SET_REST_START = 0x21E, + SMSG_SET_REST_START_OBSOLETE = 0x21E, CMSG_SKILL_BUY_STEP = 0x21F, CMSG_SKILL_BUY_RANK = 0x220, CMSG_XP_CHEAT = 0x221, @@ -733,8 +733,8 @@ enum Opcodes SMSG_SCRIPT_MESSAGE = 0x2B6, SMSG_DUEL_COUNTDOWN = 0x2B7, SMSG_AREA_TRIGGER_MESSAGE = 0x2B8, - CMSG_TOGGLE_HELM = 0x2B9, - CMSG_TOGGLE_CLOAK = 0x2BA, + CMSG_SHOWING_HELM = 0x2B9, + CMSG_SHOWING_CLOAK = 0x2BA, SMSG_MEETINGSTONE_JOINFAILED = 0x2BB, SMSG_PLAYER_SKINNED = 0x2BC, SMSG_DURABILITY_DAMAGE_DEATH = 0x2BD, @@ -967,10 +967,10 @@ enum Opcodes SMSG_VOICE_SESSION_ADJUST_PRIORITY = 0x3A0, CMSG_VOICE_SET_TALKER_MUTED_REQUEST = 0x3A1, SMSG_VOICE_SET_TALKER_MUTED = 0x3A2, - SMSG_INIT_EXTRA_AURA_INFO = 0x3A3, - SMSG_SET_EXTRA_AURA_INFO = 0x3A4, - SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE = 0x3A5, - SMSG_CLEAR_EXTRA_AURA_INFO = 0x3A6, + SMSG_INIT_EXTRA_AURA_INFO_OBSOLETE = 0x3A3, + SMSG_SET_EXTRA_AURA_INFO_OBSOLETE = 0x3A4, + SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE_OBSOLETE = 0x3A5, + SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE = 0x3A6, MSG_MOVE_START_DESCEND = 0x3A7, CMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A8, SMSG_IGNORE_REQUIREMENTS_CHEAT = 0x3A9, @@ -980,127 +980,262 @@ enum Opcodes MSG_MOVE_UPDATE_CAN_FLY = 0x3AD, MSG_RAID_READY_CHECK_CONFIRM = 0x3AE, CMSG_VOICE_SESSION_ENABLE = 0x3AF, - SMSG_VOICE_PARENTAL_CONTROLS = 0x3B0, - CMSG_GM_WHISPER = 0x3B1, - SMSG_GM_MESSAGECHAT = 0x3B2, - MSG_GM_GEARRATING = 0x3B3, - CMSG_COMMENTATOR_ENABLE = 0x3B4, - SMSG_COMMENTATOR_STATE_CHANGED = 0x3B5, - CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B6, - SMSG_COMMENTATOR_MAP_INFO = 0x3B7, - CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B8, - SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9, - SMSG_COMMENTATOR_PLAYER_INFO = 0x3BA, - CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BB, - CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BC, - CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BD, - SMSG_CLEAR_TARGET = 0x3BE, - CMSG_BOT_DETECTED = 0x3BF, - SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C0, - CMSG_CHEAT_PLAYER_LOGIN = 0x3C1, - CMSG_CHEAT_PLAYER_LOOKUP = 0x3C2, - SMSG_CHEAT_PLAYER_LOOKUP = 0x3C3, - SMSG_KICK_REASON = 0x3C4, - MSG_RAID_READY_CHECK_FINISHED = 0x3C5, - CMSG_COMPLAIN = 0x3C6, - SMSG_COMPLAIN_RESULT = 0x3C7, - SMSG_FEATURE_SYSTEM_STATUS = 0x3C8, - CMSG_GM_SHOW_COMPLAINTS = 0x3C9, - CMSG_GM_UNSQUELCH = 0x3CA, - CMSG_CHANNEL_SILENCE_VOICE = 0x3CB, - CMSG_CHANNEL_SILENCE_ALL = 0x3CC, - CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CD, - CMSG_CHANNEL_UNSILENCE_ALL = 0x3CE, - CMSG_TARGET_CAST = 0x3CF, - CMSG_TARGET_SCRIPT_CAST = 0x3D0, - CMSG_CHANNEL_DISPLAY_LIST = 0x3D1, - CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D2, - CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D3, - SMSG_CHANNEL_MEMBER_COUNT = 0x3D4, - CMSG_CHANNEL_VOICE_ON = 0x3D5, - CMSG_CHANNEL_VOICE_OFF = 0x3D6, - CMSG_DEBUG_LIST_TARGETS = 0x3D7, - SMSG_DEBUG_LIST_TARGETS = 0x3D8, - SMSG_AVAILABLE_VOICE_CHANNEL = 0x3D9, - CMSG_ADD_VOICE_IGNORE = 0x3DA, - CMSG_DEL_VOICE_IGNORE = 0x3DB, - CMSG_PARTY_SILENCE = 0x3DC, - CMSG_PARTY_UNSILENCE = 0x3DD, - MSG_NOTIFY_PARTY_SQUELCH = 0x3DE, - SMSG_COMSAT_RECONNECT_TRY = 0x3DF, - SMSG_COMSAT_DISCONNECT = 0x3E0, - SMSG_COMSAT_CONNECT_FAIL = 0x3E1, - SMSG_VOICE_CHAT_STATUS = 0x3E2, - CMSG_REPORT_PVP_AFK = 0x3E3, - CMSG_REPORT_PVP_AFK_RESULT = 0x3E4, - CMSG_GUILD_BANKER_ACTIVATE = 0x3E5, - CMSG_GUILD_BANK_QUERY_TAB = 0x3E6, - SMSG_GUILD_BANK_LIST = 0x3E7, - CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E8, - CMSG_GUILD_BANK_BUY_TAB = 0x3E9, - CMSG_GUILD_BANK_UPDATE_TAB = 0x3EA, - CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EB, - CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3EC, - MSG_GUILD_BANK_LOG_QUERY = 0x3ED, - CMSG_SET_CHANNEL_WATCH = 0x3EE, - SMSG_USERLIST_ADD = 0x3EF, - SMSG_USERLIST_REMOVE = 0x3F0, - SMSG_USERLIST_UPDATE = 0x3F1, - CMSG_CLEAR_CHANNEL_WATCH = 0x3F2, - SMSG_INSPECT_TALENT = 0x3F3, - SMSG_GOGOGO_OBSOLETE = 0x3F4, - SMSG_ECHO_PARTY_SQUELCH = 0x3F5, - CMSG_SET_TITLE_SUFFIX = 0x3F6, - CMSG_SPELLCLICK = 0x3F7, - SMSG_LOOT_LIST = 0x3F8, - CMSG_GM_CHARACTER_RESTORE = 0x3F9, - CMSG_GM_CHARACTER_SAVE = 0x3FA, - SMSG_VOICESESSION_FULL = 0x3FB, - MSG_GUILD_PERMISSIONS = 0x3FC, - MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FD, - MSG_GUILD_EVENT_LOG_QUERY = 0x3FE, - CMSG_MAELSTROM_RENAME_GUILD = 0x3FF, - CMSG_GET_MIRRORIMAGE_DATA = 0x400, - SMSG_MIRRORIMAGE_DATA = 0x401, - SMSG_FORCE_DISPLAY_UPDATE = 0x402, - SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x403, - CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x404, - SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405, - CMSG_KEEP_ALIVE = 0x406, - SMSG_RAID_READY_CHECK_ERROR = 0x407, - CMSG_OPT_OUT_OF_LOOT = 0x408, - MSG_QUERY_GUILD_BANK_TEXT = 0x409, - CMSG_SET_GUILD_BANK_TEXT = 0x40A, - CMSG_SET_GRANTABLE_LEVELS = 0x40B, - CMSG_GRANT_LEVEL = 0x40C, - CMSG_REFER_A_FRIEND = 0x40D, - MSG_GM_CHANGE_ARENA_RATING = 0x40E, - CMSG_DECLINE_CHANNEL_INVITE = 0x40F, - CMSG_GROUPACTION_THROTTLED = 0x410, - SMSG_OVERRIDE_LIGHT = 0x411, - SMSG_TOTEM_CREATED = 0x412, - CMSG_TOTEM_DESTROYED = 0x413, - CMSG_EXPIRE_RAID_INSTANCE = 0x414, - CMSG_NO_SPELL_VARIANCE = 0x415, - CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x416, - SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x417, - CMSG_SET_PLAYER_DECLINED_NAMES = 0x418, - SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x419, - CMSG_QUERY_SERVER_BUCK_DATA = 0x41A, - CMSG_CLEAR_SERVER_BUCK_DATA = 0x41B, - SMSG_SERVER_BUCK_DATA = 0x41C, - SMSG_SEND_UNLEARN_SPELLS = 0x41D, - SMSG_PROPOSE_LEVEL_GRANT = 0x41E, - CMSG_ACCEPT_LEVEL_GRANT = 0x41F, - SMSG_REFER_A_FRIEND_FAILURE = 0x420, - SMSG_SPLINE_MOVE_SET_FLYING = 0x421, - SMSG_SPLINE_MOVE_UNSET_FLYING = 0x422, - SMSG_SUMMON_CANCEL = 0x423 + SMSG_VOICE_SESSION_ENABLE = 0x3B0, + SMSG_VOICE_PARENTAL_CONTROLS = 0x3B1, + CMSG_GM_WHISPER = 0x3B2, + SMSG_GM_MESSAGECHAT = 0x3B3, + MSG_GM_GEARRATING = 0x3B4, + CMSG_COMMENTATOR_ENABLE = 0x3B5, + SMSG_COMMENTATOR_STATE_CHANGED = 0x3B6, + CMSG_COMMENTATOR_GET_MAP_INFO = 0x3B7, + SMSG_COMMENTATOR_MAP_INFO = 0x3B8, + CMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3B9, + SMSG_COMMENTATOR_GET_PLAYER_INFO = 0x3BA, + SMSG_COMMENTATOR_PLAYER_INFO = 0x3BB, + CMSG_COMMENTATOR_ENTER_INSTANCE = 0x3BC, + CMSG_COMMENTATOR_EXIT_INSTANCE = 0x3BD, + CMSG_COMMENTATOR_INSTANCE_COMMAND = 0x3BE, + SMSG_CLEAR_TARGET = 0x3BF, + CMSG_BOT_DETECTED = 0x3C0, + SMSG_CROSSED_INEBRIATION_THRESHOLD = 0x3C1, + CMSG_CHEAT_PLAYER_LOGIN = 0x3C2, + CMSG_CHEAT_PLAYER_LOOKUP = 0x3C3, + SMSG_CHEAT_PLAYER_LOOKUP = 0x3C4, + SMSG_KICK_REASON = 0x3C5, + MSG_RAID_READY_CHECK_FINISHED = 0x3C6, + CMSG_COMPLAIN = 0x3C7, + SMSG_COMPLAIN_RESULT = 0x3C8, + SMSG_FEATURE_SYSTEM_STATUS = 0x3C9, + CMSG_GM_SHOW_COMPLAINTS = 0x3CA, + CMSG_GM_UNSQUELCH = 0x3CB, + CMSG_CHANNEL_SILENCE_VOICE = 0x3CC, + CMSG_CHANNEL_SILENCE_ALL = 0x3CD, + CMSG_CHANNEL_UNSILENCE_VOICE = 0x3CE, + CMSG_CHANNEL_UNSILENCE_ALL = 0x3CF, + CMSG_TARGET_CAST = 0x3D0, + CMSG_TARGET_SCRIPT_CAST = 0x3D1, + CMSG_CHANNEL_DISPLAY_LIST = 0x3D2, + CMSG_SET_ACTIVE_VOICE_CHANNEL = 0x3D3, + CMSG_GET_CHANNEL_MEMBER_COUNT = 0x3D4, + SMSG_CHANNEL_MEMBER_COUNT = 0x3D5, + CMSG_CHANNEL_VOICE_ON = 0x3D6, + CMSG_CHANNEL_VOICE_OFF = 0x3D7, + CMSG_DEBUG_LIST_TARGETS = 0x3D8, + SMSG_DEBUG_LIST_TARGETS = 0x3D9, + SMSG_AVAILABLE_VOICE_CHANNEL = 0x3DA, + CMSG_ADD_VOICE_IGNORE = 0x3DB, + CMSG_DEL_VOICE_IGNORE = 0x3DC, + CMSG_PARTY_SILENCE = 0x3DD, + CMSG_PARTY_UNSILENCE = 0x3DE, + MSG_NOTIFY_PARTY_SQUELCH = 0x3DF, + SMSG_COMSAT_RECONNECT_TRY = 0x3E0, + SMSG_COMSAT_DISCONNECT = 0x3E1, + SMSG_COMSAT_CONNECT_FAIL = 0x3E2, + SMSG_VOICE_CHAT_STATUS = 0x3E3, + CMSG_REPORT_PVP_AFK = 0x3E4, + CMSG_REPORT_PVP_AFK_RESULT = 0x3E5, + CMSG_GUILD_BANKER_ACTIVATE = 0x3E6, + CMSG_GUILD_BANK_QUERY_TAB = 0x3E7, + SMSG_GUILD_BANK_LIST = 0x3E8, + CMSG_GUILD_BANK_SWAP_ITEMS = 0x3E9, + CMSG_GUILD_BANK_BUY_TAB = 0x3EA, + CMSG_GUILD_BANK_UPDATE_TAB = 0x3EB, + CMSG_GUILD_BANK_DEPOSIT_MONEY = 0x3EC, + CMSG_GUILD_BANK_WITHDRAW_MONEY = 0x3ED, + MSG_GUILD_BANK_LOG_QUERY = 0x3EE, + CMSG_SET_CHANNEL_WATCH = 0x3EF, + SMSG_USERLIST_ADD = 0x3F0, + SMSG_USERLIST_REMOVE = 0x3F1, + SMSG_USERLIST_UPDATE = 0x3F2, + CMSG_CLEAR_CHANNEL_WATCH = 0x3F3, + SMSG_INSPECT_TALENT = 0x3F4, + SMSG_GOGOGO_OBSOLETE = 0x3F5, + SMSG_ECHO_PARTY_SQUELCH = 0x3F6, + CMSG_SET_TITLE_SUFFIX = 0x3F7, + CMSG_SPELLCLICK = 0x3F8, + SMSG_LOOT_LIST = 0x3F9, + CMSG_GM_CHARACTER_RESTORE = 0x3FA, + CMSG_GM_CHARACTER_SAVE = 0x3FB, + SMSG_VOICESESSION_FULL = 0x3FC, + MSG_GUILD_PERMISSIONS = 0x3FD, + MSG_GUILD_BANK_MONEY_WITHDRAWN = 0x3FE, + MSG_GUILD_EVENT_LOG_QUERY = 0x3FF, + CMSG_MAELSTROM_RENAME_GUILD = 0x400, + CMSG_GET_MIRRORIMAGE_DATA = 0x401, + SMSG_MIRRORIMAGE_DATA = 0x402, + SMSG_FORCE_DISPLAY_UPDATE = 0x403, + SMSG_SPELL_CHANCE_RESIST_PUSHBACK = 0x404, + CMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x405, + SMSG_IGNORE_DIMINISHING_RETURNS_CHEAT = 0x406, + CMSG_KEEP_ALIVE = 0x407, + SMSG_RAID_READY_CHECK_ERROR = 0x408, + CMSG_OPT_OUT_OF_LOOT = 0x409, + MSG_QUERY_GUILD_BANK_TEXT = 0x40A, + CMSG_SET_GUILD_BANK_TEXT = 0x40B, + CMSG_SET_GRANTABLE_LEVELS = 0x40C, + CMSG_GRANT_LEVEL = 0x40D, + CMSG_REFER_A_FRIEND = 0x40E, + MSG_GM_CHANGE_ARENA_RATING = 0x40F, + CMSG_DECLINE_CHANNEL_INVITE = 0x410, + CMSG_GROUPACTION_THROTTLED = 0x411, + SMSG_OVERRIDE_LIGHT = 0x412, + SMSG_TOTEM_CREATED = 0x413, + CMSG_TOTEM_DESTROYED = 0x414, + CMSG_EXPIRE_RAID_INSTANCE = 0x415, + CMSG_NO_SPELL_VARIANCE = 0x416, + CMSG_QUESTGIVER_STATUS_MULTIPLE_QUERY = 0x417, + SMSG_QUESTGIVER_STATUS_MULTIPLE = 0x418, + CMSG_SET_PLAYER_DECLINED_NAMES = 0x419, + SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0x41A, + CMSG_QUERY_SERVER_BUCK_DATA = 0x41B, + CMSG_CLEAR_SERVER_BUCK_DATA = 0x41C, + SMSG_SERVER_BUCK_DATA = 0x41D, + SMSG_SEND_UNLEARN_SPELLS = 0x41E, + SMSG_PROPOSE_LEVEL_GRANT = 0x41F, + CMSG_ACCEPT_LEVEL_GRANT = 0x420, + SMSG_REFER_A_FRIEND_FAILURE = 0x421, + SMSG_SPLINE_MOVE_SET_FLYING = 0x422, + SMSG_SPLINE_MOVE_UNSET_FLYING = 0x423, + SMSG_SUMMON_CANCEL = 0x424, + CMSG_CHANGE_PERSONAL_ARENA_RATING = 0x425, + CMSG_ALTER_APPEARANCE = 0x426, + SMSG_ENABLE_BARBER_SHOP = 0x427, + SMSG_BARBER_SHOP_RESULT = 0x428, + CMSG_CALENDAR_GET_CALENDAR = 0x429, + CMSG_CALENDAR_GET_EVENT = 0x42A, + CMSG_CALENDAR_GUILD_FILTER = 0x42B, + CMSG_CALENDAR_ARENA_TEAM = 0x42C, + CMSG_CALENDAR_ADD_EVENT = 0x42D, + CMSG_CALENDAR_UPDATE_EVENT = 0x42E, + CMSG_CALENDAR_REMOVE_EVENT = 0x42F, + CMSG_CALENDAR_COPY_EVENT = 0x430, + CMSG_CALENDAR_EVENT_INVITE = 0x431, + CMSG_CALENDAR_EVENT_RSVP = 0x432, + CMSG_CALENDAR_EVENT_REMOVE_INVITE = 0x433, + CMSG_CALENDAR_EVENT_STATUS = 0x434, + CMSG_CALENDAR_EVENT_MODERATOR_STATUS = 0x435, + SMSG_CALENDAR_SEND_CALENDAR = 0x436, + SMSG_CALENDAR_SEND_EVENT = 0x437, + SMSG_CALENDAR_FILTER_GUILD = 0x438, + SMSG_CALENDAR_ARENA_TEAM = 0x439, + SMSG_CALENDAR_EVENT_INVITE = 0x43A, + SMSG_CALENDAR_EVENT_INVITE_REMOVED = 0x43B, + SMSG_CALENDAR_EVENT_STATUS = 0x43C, + SMSG_CALENDAR_COMMAND_RESULT = 0x43D, + SMSG_CALENDAR_RAID_LOCKOUT_ADDED = 0x43E, + SMSG_CALENDAR_RAID_LOCKOUT_REMOVED = 0x43F, + SMSG_CALENDAR_EVENT_INVITE_ALERT = 0x440, + SMSG_CALENDAR_EVENT_INVITE_REMOVED_ALERT = 0x441, + SMSG_CALENDAR_EVENT_INVITE_STATUS_ALERT = 0x442, + SMSG_CALENDAR_EVENT_REMOVED_ALERT = 0x443, + SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x444, + SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x445, + CMSG_CALENDAR_COMPLAIN = 0x446, + CMSG_CALENDAR_GET_NUM_PENDING = 0x447, + SMSG_CALENDAR_SEND_NUM_PENDING = 0x448, + CMSG_SAVE_DANCE = 0x449, + SMSG_NOTIFY_DANCE = 0x44A, + CMSG_PLAY_DANCE = 0x44B, + SMSG_PLAY_DANCE = 0x44C, + CMSG_LOAD_DANCES = 0x44D, + CMSG_STOP_DANCE = 0x44E, + SMSG_STOP_DANCE = 0x44F, + CMSG_SYNC_DANCE = 0x450, + CMSG_DANCE_QUERY = 0x451, + SMSG_DANCE_QUERY_RESPONSE = 0x452, + SMSG_INVALIDATE_DANCE = 0x453, + CMSG_DELETE_DANCE = 0x454, + SMSG_LEARNED_DANCE_MOVES = 0x455, + CMSG_LEARN_DANCE_MOVE = 0x456, + CMSG_UNLEARN_DANCE_MOVE = 0x457, + CMSG_SET_RUNE_COUNT = 0x458, + CMSG_SET_RUNE_COOLDOWN = 0x459, + MSG_MOVE_SET_PITCH_RATE_CHEAT = 0x45A, + MSG_MOVE_SET_PITCH_RATE = 0x45B, + SMSG_FORCE_PITCH_RATE_CHANGE = 0x45C, + CMSG_FORCE_PITCH_RATE_CHANGE_ACK = 0x45D, + SMSG_SPLINE_SET_PITCH_RATE = 0x45E, + SMSG_MOVE_ABANDON_TRANSPORT = 0x45F, + MSG_MOVE_ABANDON_TRANSPORT = 0x460, + CMSG_MOVE_ABANDON_TRANSPORT_ACK = 0x461, + CMSG_UPDATE_MISSILE_TRAJECTORY = 0x462, + SMSG_UPDATE_ACCOUNT_DATA_COMPLETE = 0x463, + SMSG_TRIGGER_MOVIE = 0x464, + CMSG_COMPLETE_MOVIE = 0x465, + CMSG_SET_GLYPH_SLOT = 0x466, + CMSG_SET_GLYPH = 0x467, + SMSG_ACHIEVEMENT_EARNED = 0x468, + SMSG_DYNAMIC_DROP_ROLL_RESULT = 0x469, + SMSG_CRITERIA_UPDATE = 0x46A, + CMSG_QUERY_INSPECT_ACHIEVEMENTS = 0x46B, + SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0x46C, + CMSG_DISMISS_CONTROLLED_VEHICLE = 0x46D, + CMSG_COMPLETE_ACHIEVEMENT_CHEAT = 0x46E, + SMSG_QUESTUPDATE_ADD_PVP_KILL = 0x46F, + CMSG_SET_CRITERIA_CHEAT = 0x470, + SMSG_GROUP_SWAP_FAILED = 0x471, + CMSG_UNITANIMTIER_CHEAT = 0x472, + CMSG_CHAR_CUSTOMIZE = 0x473, + SMSG_CHAR_CUSTOMIZE = 0x474, + SMSG_PET_RENAMEABLE = 0x475, + CMSG_REQUEST_VEHICLE_EXIT = 0x476, + CMSG_REQUEST_VEHICLE_PREV_SEAT = 0x477, + CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0x478, + CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0x479, + CMSG_PET_LEARN_TALENT = 0x47A, + CMSG_PET_UNLEARN_TALENTS = 0x47B, + SMSG_SET_PHASE_SHIFT = 0x47C, + SMSG_ALL_ACHIEVEMENT_DATA = 0x47D, + CMSG_FORCE_SAY_CHEAT = 0x47E, + SMSG_HEALTH_UPDATE = 0x47F, + SMSG_POWER_UPDATE = 0x480, + CMSG_GAMEOBJ_REPORT_USE = 0x481, + SMSG_HIGHEST_THREAT_UPDATE = 0x482, + SMSG_THREAT_UPDATE = 0x483, + SMSG_THREAT_REMOVE = 0x484, + SMSG_THREAT_CLEAR = 0x485, + SMSG_CONVERT_RUNE = 0x486, + SMSG_RESYNC_RUNES = 0x487, + SMSG_ADD_RUNE_POWER = 0x488, + CMSG_START_QUEST = 0x489, + CMSG_REMOVE_GLYPH = 0x48A, + CMSG_DUMP_OBJECTS = 0x48B, + SMSG_DUMP_OBJECTS_DATA = 0x48C, + CMSG_DISMISS_CRITTER = 0x48D, + SMSG_NOTIFY_DEST_LOC_SPELL_CAST = 0x48E, + CMSG_AUCTION_LIST_PENDING_SALES = 0x48F, + SMSG_AUCTION_LIST_PENDING_SALES = 0x490, + SMSG_MODIFY_COOLDOWN = 0x491, + SMSG_PET_UPDATE_COMBO_POINTS = 0x492, + CMSG_ENABLETAXI = 0x493, + SMSG_PRE_RESURRECT = 0x494, + SMSG_AURA_UPDATE_ALL = 0x495, + SMSG_AURA_UPDATE = 0x496, + CMSG_FLOOD_GRACE_CHEAT = 0x497, + SMSG_SERVER_FIRST_ACHIEVEMENT = 0x498, + SMSG_PET_LEARNED_SPELL = 0x499, + SMSG_PET_REMOVED_SPELL = 0x49A, + CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE = 0x49B, + CMSG_HEARTH_AND_RESURRECT = 0x49C, + SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x49D, + SMSG_CRITERIA_DELETED = 0x49E, + SMSG_ACHIEVEMENT_DELETED = 0x49F, + CMSG_SERVER_INFO_QUERY = 0x4A0, + SMSG_SERVER_INFO_RESPONSE = 0x4A1, + CMSG_CHECK_LOGIN_CRITERIA = 0x4A2, + SMSG_SERVER_BUCK_DATA_START = 0x4A3, + CMSG_QUERY_VEHICLE_STATUS = 0x4A4, + SMSG_PET_GUIDS = 0x4A5, + SMSG_CLIENTCACHE_VERSION = 0x4A6, + UMSG_UNKNOWN_1191 = 0x4A7, + UMSG_UNKNOWN_1192 = 0x4A8, + UMSG_UNKNOWN_1193 = 0x4A9, + UMSG_UNKNOWN_1194 = 0x4AA, + UMSG_UNKNOWN_1195 = 0x4AB, + UMSG_UNKNOWN_1196 = 0x4AC, + NUM_MSG_TYPES = 0x4AD }; -// Don't forget to change this value and add opcode name to Opcodes.cpp when you add new opcode! -#define NUM_MSG_TYPES 0x424 - /// Player state enum SessionStatus { diff --git a/src/game/OutdoorPvP.cpp b/src/game/OutdoorPvP.cpp index a6f050c5a62..adbe220fbe5 100644 --- a/src/game/OutdoorPvP.cpp +++ b/src/game/OutdoorPvP.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -95,7 +95,7 @@ bool OutdoorPvPObjective::AddObject(uint32 type, uint32 entry, uint32 map, float if(!pMap) return true; GameObject * go = new GameObject; - if(!go->Create(guid,entry, pMap,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1)) + if(!go->Create(guid,entry, pMap,PHASEMASK_NORMAL,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1)) { sLog.outError("Gameobject template %u not found in database.", entry); delete go; @@ -156,7 +156,7 @@ bool OutdoorPvPObjective::AddCreature(uint32 type, uint32 entry, uint32 teamval, if(!pMap) return true; Creature* pCreature = new Creature; - if (!pCreature->Create(guid, pMap, entry, teamval)) + if (!pCreature->Create(guid, pMap, PHASEMASK_NORMAL, entry, teamval)) { sLog.outError("Can't create creature entry: %u",entry); delete pCreature; @@ -256,7 +256,7 @@ bool OutdoorPvPObjective::AddCapturePoint(uint32 entry, uint32 map, float x, flo return true; // add GO... GameObject * go = new GameObject; - if(!go->Create(guid,entry, pMap,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1)) + if(!go->Create(guid,entry, pMap,PHASEMASK_NORMAL,x,y,z,o,rotation0,rotation1,rotation2,rotation3,100,1)) { sLog.outError("Gameobject template %u not found in database.", entry); delete go; @@ -269,7 +269,7 @@ bool OutdoorPvPObjective::AddCapturePoint(uint32 entry, uint32 map, float x, flo } // add creature... Creature* pCreature = new Creature; - if (!pCreature->Create(creature_guid, pMap, OPVP_TRIGGER_CREATURE_ENTRY, 0)) + if (!pCreature->Create(creature_guid, pMap, PHASEMASK_NORMAL, OPVP_TRIGGER_CREATURE_ENTRY, 0)) { sLog.outError("Can't create creature entry: %u",entry); delete pCreature; diff --git a/src/game/OutdoorPvP.h b/src/game/OutdoorPvP.h index 5643c5f3148..542863a5341 100644 --- a/src/game/OutdoorPvP.h +++ b/src/game/OutdoorPvP.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPEP.cpp b/src/game/OutdoorPvPEP.cpp index 93064c85d88..c403a5dc094 100644 --- a/src/game/OutdoorPvPEP.cpp +++ b/src/game/OutdoorPvPEP.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPEP.h b/src/game/OutdoorPvPEP.h index d454848e249..2a6a47827d6 100644 --- a/src/game/OutdoorPvPEP.h +++ b/src/game/OutdoorPvPEP.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPHP.cpp b/src/game/OutdoorPvPHP.cpp index ced9bcf09e6..7294db0fb77 100644 --- a/src/game/OutdoorPvPHP.cpp +++ b/src/game/OutdoorPvPHP.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPHP.h b/src/game/OutdoorPvPHP.h index dd274097dfa..986e8daee7e 100644 --- a/src/game/OutdoorPvPHP.h +++ b/src/game/OutdoorPvPHP.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPMgr.cpp b/src/game/OutdoorPvPMgr.cpp index 7f1ffa3faa6..757cbe82188 100644 --- a/src/game/OutdoorPvPMgr.cpp +++ b/src/game/OutdoorPvPMgr.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPMgr.h b/src/game/OutdoorPvPMgr.h index 033f67d97d3..2478acf76f4 100644 --- a/src/game/OutdoorPvPMgr.h +++ b/src/game/OutdoorPvPMgr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPNA.cpp b/src/game/OutdoorPvPNA.cpp index 827f988a959..c8134944cc1 100644 --- a/src/game/OutdoorPvPNA.cpp +++ b/src/game/OutdoorPvPNA.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPNA.h b/src/game/OutdoorPvPNA.h index a833a6d95b2..e7f157879bc 100644 --- a/src/game/OutdoorPvPNA.h +++ b/src/game/OutdoorPvPNA.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPObjectiveAI.cpp b/src/game/OutdoorPvPObjectiveAI.cpp index b907fa7cdba..6e6cf8d64e5 100644 --- a/src/game/OutdoorPvPObjectiveAI.cpp +++ b/src/game/OutdoorPvPObjectiveAI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPObjectiveAI.h b/src/game/OutdoorPvPObjectiveAI.h index 4b65c72e6f9..3395b7e1be5 100644 --- a/src/game/OutdoorPvPObjectiveAI.h +++ b/src/game/OutdoorPvPObjectiveAI.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPSI.cpp b/src/game/OutdoorPvPSI.cpp index b2bbc8a109b..9e95c315c7f 100644 --- a/src/game/OutdoorPvPSI.cpp +++ b/src/game/OutdoorPvPSI.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -202,7 +202,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player *plr, uint32 spellId) Map * map = MapManager::Instance().GetMap(plr->GetMapId(), plr); if(!map) return true; - if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map,plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,1)) + if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map, plr->GetPhaseMask(), plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,1)) { delete go; } @@ -228,7 +228,7 @@ bool OutdoorPvPSI::HandleDropFlag(Player *plr, uint32 spellId) Map * map = MapManager::Instance().GetMap(plr->GetMapId(), plr); if(!map) return true; - if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map ,plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,1)) + if(!go->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT),SI_SILITHYST_MOUND, map, plr->GetPhaseMask() ,plr->GetPositionX(),plr->GetPositionY(),plr->GetPositionZ(),plr->GetOrientation(),0,0,0,0,100,1)) { delete go; } diff --git a/src/game/OutdoorPvPSI.h b/src/game/OutdoorPvPSI.h index 0eb07af508f..208e35d09a1 100644 --- a/src/game/OutdoorPvPSI.h +++ b/src/game/OutdoorPvPSI.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPTF.cpp b/src/game/OutdoorPvPTF.cpp index bd8355de667..39acc70ba53 100644 --- a/src/game/OutdoorPvPTF.cpp +++ b/src/game/OutdoorPvPTF.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPZM.cpp b/src/game/OutdoorPvPZM.cpp index be2a8c7f093..d8ac0de5f7d 100644 --- a/src/game/OutdoorPvPZM.cpp +++ b/src/game/OutdoorPvPZM.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/OutdoorPvPZM.h b/src/game/OutdoorPvPZM.h index 8ccbe77f363..c99ad69fa22 100644 --- a/src/game/OutdoorPvPZM.h +++ b/src/game/OutdoorPvPZM.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Path.h b/src/game/Path.h index 2bf7cfa4d6b..fe1c3587caf 100644 --- a/src/game/Path.h +++ b/src/game/Path.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 72951420573..bf150ec3a42 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,46 +41,14 @@ char const* petTypeSuffix[MAX_PET_TYPE] = "'s Companion" // MINI_PET }; -//numbers represent minutes * 100 while happy (you get 100 loyalty points per min while happy) -uint32 const LevelUpLoyalty[6] = -{ - 5500, - 11500, - 17000, - 23500, - 31000, - 39500, -}; - -uint32 const LevelStartLoyalty[6] = -{ - 2000, - 4500, - 7000, - 10000, - 13500, - 17500, -}; - -Pet::Pet(PetType type) : Creature() +Pet::Pet(PetType type) : +Creature(), m_petType(type), m_removed(false), m_happinessTimer(7500), m_duration(0), m_bonusdamage(0), +m_resetTalentsCost(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraRaidUpdateMask(0), m_loading(false), +m_declinedname(NULL) { m_isPet = true; m_name = "Pet"; - m_petType = type; - - m_removed = false; m_regenTimer = 4000; - m_happinessTimer = 7500; - m_loyaltyTimer = 12000; - m_duration = 0; - m_bonusdamage = 0; - - m_loyaltyPoints = 0; - m_TrainingPoints = 0; - m_resetTalentsCost = 0; - m_resetTalentsTime = 0; - - m_auraUpdateMask = 0; // pets always have a charminfo, even if they are not actually charmed CharmInfo* charmInfo = InitCharmInfo(this); @@ -90,12 +58,6 @@ Pet::Pet(PetType type) : Creature() else if(type == GUARDIAN_PET) // always aggressive charmInfo->SetReactState(REACT_AGGRESSIVE); - m_spells.clear(); - m_Auras.clear(); - m_CreatureSpellCooldowns.clear(); - m_CreatureCategoryCooldowns.clear(); - m_autospells.clear(); - m_declinedname = NULL; m_isActive = true; } @@ -126,26 +88,28 @@ void Pet::RemoveFromWorld() Unit::RemoveFromWorld(); } -bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool current ) +bool Pet::LoadPetFromDB( Player* owner, uint32 petentry, uint32 petnumber, bool current ) { + m_loading = true; + uint32 ownerid = owner->GetGUIDLow(); QueryResult *result; if(petnumber) - // known petnumber entry 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber); + // known petnumber entry 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND id = '%u'",ownerid, petnumber); else if(current) - // current pet (slot 0) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid ); + // current pet (slot 0) 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND slot = '0'",ownerid ); else if(petentry) // known petentry entry (unique for summoned pet, but non unique for hunter pet (only from current or not stabled pets) - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry ); + // 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND entry = '%u' AND (slot = '0' OR slot = '3') ",ownerid, petentry ); else // any current or other non-stabled pet (for hunter "call pet") - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 - result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid); + // 0 1 2(?) 3 4 5 6 7 8(?) 9 10 11 12 13 14 15 16 17 18 19 20 + result = CharacterDatabase.PQuery("SELECT id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3') ",ownerid); if(!result) return false; @@ -160,7 +124,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu return false; } - uint32 summon_spell_id = fields[21].GetUInt32(); + uint32 summon_spell_id = fields[19].GetUInt32(); SpellEntry const* spellInfo = sSpellStore.LookupEntry(summon_spell_id); bool is_temporary_summoned = spellInfo && GetSpellDuration(spellInfo) > 0; @@ -175,7 +139,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu Map *map = owner->GetMap(); uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_PET); uint32 pet_number = fields[0].GetUInt32(); - if(!Create(guid, map, petentry, pet_number)) + if(!Create(guid, map, owner->GetPhaseMask(), petentry, pet_number)) { delete result; return false; @@ -194,8 +158,8 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu return false; } - setPetType(PetType(fields[22].GetUInt8())); - SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction()); + setPetType(PetType(fields[20].GetUInt8())); + SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, owner->getFaction()); SetUInt32Value(UNIT_CREATED_BY_SPELL, summon_spell_id); CreatureInfo const *cinfo = GetCreatureInfo(); @@ -206,72 +170,67 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu delete result; return true; } - if(getPetType()==HUNTER_PET || (getPetType()==SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK)) + + if(getPetType() == HUNTER_PET || (getPetType() == SUMMON_PET && cinfo->type == CREATURE_TYPE_DEMON && owner->getClass() == CLASS_WARLOCK)) m_charmInfo->SetPetNumber(pet_number, true); else m_charmInfo->SetPetNumber(pet_number, false); - SetUInt64Value(UNIT_FIELD_SUMMONEDBY, owner->GetGUID()); + + SetOwnerGUID(owner->GetGUID()); SetDisplayId(fields[3].GetUInt32()); SetNativeDisplayId(fields[3].GetUInt32()); - uint32 petlevel=fields[4].GetUInt32(); - SetUInt32Value(UNIT_NPC_FLAGS , 0); - SetName(fields[11].GetString()); + uint32 petlevel = fields[4].GetUInt32(); + SetUInt32Value(UNIT_NPC_FLAGS, 0); + SetName(fields[9].GetString()); switch(getPetType()) { - case SUMMON_PET: petlevel=owner->getLevel(); - SetUInt32Value(UNIT_FIELD_BYTES_0,2048); + SetUInt32Value(UNIT_FIELD_BYTES_0, 2048); SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet dismiss, cancel) break; case HUNTER_PET: SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); - SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[8].GetUInt32()); - SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 ); - - if(fields[12].GetBool()) - SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED); - else - SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED); + SetByteValue(UNIT_FIELD_BYTES_1, 1, fields[7].GetUInt32()); + SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + SetByteValue(UNIT_FIELD_BYTES_2, 2, fields[10].GetBool() ? UNIT_RENAME_NOT_ALLOWED : UNIT_RENAME_ALLOWED); SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); // this enables popup window (pet abandon, cancel) - SetTP(fields[9].GetInt32()); - SetMaxPower(POWER_HAPPINESS,GetCreatePowers(POWER_HAPPINESS)); - SetPower( POWER_HAPPINESS,fields[15].GetUInt32()); + SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS)); + SetPower(POWER_HAPPINESS, fields[13].GetUInt32()); setPowerType(POWER_FOCUS); break; default: - sLog.outError("Pet have incorrect type (%u) for pet loading.",getPetType()); + sLog.outError("Pet have incorrect type (%u) for pet loading.", getPetType()); } - InitStatsForLevel( petlevel); + + InitStatsForLevel(petlevel); SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, fields[5].GetUInt32()); - SetUInt64Value(UNIT_FIELD_CREATEDBY, owner->GetGUID()); + SetCreatorGUID(owner->GetGUID()); - m_charmInfo->SetReactState( ReactStates( fields[6].GetUInt8() )); - m_loyaltyPoints = fields[7].GetInt32(); + m_charmInfo->SetReactState(ReactStates(fields[6].GetUInt8())); - uint32 savedhealth = fields[13].GetUInt32(); - uint32 savedmana = fields[14].GetUInt32(); + uint32 savedhealth = fields[11].GetUInt32(); + uint32 savedmana = fields[12].GetUInt32(); // set current pet as current - if(fields[10].GetUInt32() != 0) + if(fields[8].GetUInt32() != 0) { CharacterDatabase.BeginTransaction(); - CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'",ownerid, m_charmInfo->GetPetNumber()); - CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'",ownerid, m_charmInfo->GetPetNumber()); + CharacterDatabase.PExecute("UPDATE character_pet SET slot = '3' WHERE owner = '%u' AND slot = '0' AND id <> '%u'", ownerid, m_charmInfo->GetPetNumber()); + CharacterDatabase.PExecute("UPDATE character_pet SET slot = '0' WHERE owner = '%u' AND id = '%u'", ownerid, m_charmInfo->GetPetNumber()); CharacterDatabase.CommitTransaction(); } if(!is_temporary_summoned) { // permanent controlled pets store state in DB - Tokens tokens = StrSplit(fields[16].GetString(), " "); + Tokens tokens = StrSplit(fields[14].GetString(), " "); if(tokens.size() != 20) { @@ -290,11 +249,11 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu // patch for old data where some spells have ACT_DECIDE but should have ACT_CAST // so overwrite old state SpellEntry const *spellInfo = sSpellStore.LookupEntry(m_charmInfo->GetActionBarEntry(index)->SpellOrAction); - if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET) m_charmInfo->GetActionBarEntry(index)->Type = ACT_CAST; + if (spellInfo && spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET) m_charmInfo->GetActionBarEntry(index)->Type = ACT_ENABLED; } //init teach spells - tokens = StrSplit(fields[17].GetString(), " "); + tokens = StrSplit(fields[15].GetString(), " "); for (iter = tokens.begin(), index = 0; index < 4; ++iter, ++index) { uint32 tmp = atol((*iter).c_str()); @@ -309,7 +268,10 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu } // since last save (in seconds) - uint32 timediff = (time(NULL) - fields[18].GetUInt32()); + uint32 timediff = (time(NULL) - fields[16].GetUInt32()); + + m_resetTalentsCost = fields[17].GetUInt32(); + m_resetTalentsTime = fields[18].GetUInt64(); delete result; @@ -375,6 +337,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu } } + m_loading = false; return true; } @@ -417,10 +380,6 @@ void Pet::SavePetToDB(PetSaveMode mode) case PET_SAVE_IN_STABLE_SLOT_2: case PET_SAVE_NOT_IN_SLOT: { - uint32 loyalty =1; - if(getPetType()!=HUNTER_PET) - loyalty = GetLoyaltyLevel(); - uint32 owner = GUID_LOPART(GetOwnerGUID()); std::string name = m_name; CharacterDatabase.escape_string(name); @@ -437,7 +396,7 @@ void Pet::SavePetToDB(PetSaveMode mode) CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u' AND (slot = '0' OR slot = '3')", owner ); // save pet std::ostringstream ss; - ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, loyaltypoints, loyalty, trainpoint, slot, name, renamed, curhealth, curmana, curhappiness, abdata,TeachSpelldata,savetime,resettalents_cost,resettalents_time,CreatedBySpell,PetType) " + ss << "INSERT INTO character_pet ( id, entry, owner, modelid, level, exp, Reactstate, talentpoints, slot, name, renamed, curhealth, curmana, curhappiness, abdata, TeachSpelldata, savetime, resettalents_cost, resettalents_time, CreatedBySpell, PetType) " << "VALUES (" << m_charmInfo->GetPetNumber() << ", " << GetEntry() << ", " @@ -446,9 +405,7 @@ void Pet::SavePetToDB(PetSaveMode mode) << getLevel() << ", " << GetUInt32Value(UNIT_FIELD_PETEXPERIENCE) << ", " << uint32(m_charmInfo->GetReactState()) << ", " - << m_loyaltyPoints << ", " - << GetLoyaltyLevel() << ", " - << m_TrainingPoints << ", " + << uint32(GetFreeTalentPoints()) << ", " << uint32(mode) << ", '" << name.c_str() << "', " << uint32((GetByteValue(UNIT_FIELD_BYTES_2, 2) == UNIT_RENAME_ALLOWED)?0:1) << ", " @@ -521,12 +478,12 @@ void Pet::setDeathState(DeathState s) // overwrite virtual if(!mapEntry || (mapEntry->map_type != MAP_ARENA && mapEntry->map_type != MAP_BATTLEGROUND)) ModifyPower(POWER_HAPPINESS, -HAPPINESS_LEVEL_SIZE); - SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } } else if(getDeathState()==ALIVE) { - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); CastPetAuras(true); } } @@ -553,6 +510,7 @@ void Pet::Update(uint32 diff) // unsummon pet that lost owner Unit* owner = GetOwner(); if(!owner || (!IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) && !isPossessed()) || isControlled() && !owner->GetPetGUID()) + //if(!owner || (!IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) && (owner->GetCharmGUID() && (owner->GetCharmGUID() != GetGUID()))) || (isControlled() && !owner->GetPetGUID())) { Remove(PET_SAVE_NOT_IN_SLOT, true); return; @@ -598,14 +556,6 @@ void Pet::Update(uint32 diff) else m_happinessTimer -= diff; - if(m_loyaltyTimer <= diff) - { - TickLoyaltyChange(); - m_loyaltyTimer = 12000; - } - else - m_loyaltyTimer -= diff; - break; } default: @@ -627,7 +577,7 @@ void Pet::RegenerateFocus() AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); for(AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) if ((*i)->GetModifier()->m_miscvalue == POWER_FOCUS) - addvalue *= ((*i)->GetModifierValue() + 100) / 100.0f; + addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f; ModifyPower(POWER_FOCUS, (int32)addvalue); } @@ -637,83 +587,12 @@ void Pet::LooseHappiness() uint32 curValue = GetPower(POWER_HAPPINESS); if (curValue <= 0) return; - int32 addvalue = (140 >> GetLoyaltyLevel()) * 125; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs) + int32 addvalue = 670; //value is 70/35/17/8/4 (per min) * 1000 / 8 (timer 7.5 secs) if(isInCombat()) //we know in combat happiness fades faster, multiplier guess addvalue = int32(addvalue * 1.5); ModifyPower(POWER_HAPPINESS, -addvalue); } -void Pet::ModifyLoyalty(int32 addvalue) -{ - uint32 loyaltylevel = GetLoyaltyLevel(); - - if(addvalue > 0) //only gain influenced, not loss - addvalue = int32((float)addvalue * sWorld.getRate(RATE_LOYALTY)); - - if(loyaltylevel >= BEST_FRIEND && (addvalue + m_loyaltyPoints) > int32(GetMaxLoyaltyPoints(loyaltylevel))) - return; - - m_loyaltyPoints += addvalue; - - if(m_loyaltyPoints < 0) - { - if(loyaltylevel > REBELLIOUS) - { - //level down - --loyaltylevel; - SetLoyaltyLevel(LoyaltyLevel(loyaltylevel)); - m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel); - SetTP(m_TrainingPoints - int32(getLevel())); - } - else - { - m_loyaltyPoints = 0; - Unit* owner = GetOwner(); - if(owner && owner->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_PET_BROKEN, 0); - ((Player*)owner)->GetSession()->SendPacket(&data); - - //run away - ((Player*)owner)->RemovePet(this,PET_SAVE_AS_DELETED); - } - } - } - //level up - else if(m_loyaltyPoints > int32(GetMaxLoyaltyPoints(loyaltylevel))) - { - ++loyaltylevel; - SetLoyaltyLevel(LoyaltyLevel(loyaltylevel)); - m_loyaltyPoints = GetStartLoyaltyPoints(loyaltylevel); - SetTP(m_TrainingPoints + getLevel()); - } -} - -void Pet::TickLoyaltyChange() -{ - int32 addvalue; - - switch(GetHappinessState()) - { - case HAPPY: addvalue = 20; break; - case CONTENT: addvalue = 10; break; - case UNHAPPY: addvalue = -20; break; - default: - return; - } - ModifyLoyalty(addvalue); -} - -void Pet::KillLoyaltyBonus(uint32 level) -{ - if(level > 100) - return; - - //at lower levels gain is faster | the lower loyalty the more loyalty is gained - uint32 bonus = uint32(((100 - level) / 10) + (6 - GetLoyaltyLevel())); - ModifyLoyalty(bonus); -} - HappinessState Pet::GetHappinessState() { if(GetPower(POWER_HAPPINESS) < HAPPINESS_LEVEL_SIZE) @@ -724,11 +603,6 @@ HappinessState Pet::GetHappinessState() return CONTENT; } -void Pet::SetLoyaltyLevel(LoyaltyLevel level) -{ - SetByteValue(UNIT_FIELD_BYTES_1, 1, level); -} - bool Pet::CanTakeMoreActiveSpells(uint32 spellid) { uint8 activecount = 1; @@ -765,82 +639,6 @@ bool Pet::CanTakeMoreActiveSpells(uint32 spellid) return true; } -bool Pet::HasTPForSpell(uint32 spellid) -{ - int32 neededtrainp = GetTPForSpell(spellid); - if((m_TrainingPoints - neededtrainp < 0 || neededtrainp < 0) && neededtrainp != 0) - return false; - return true; -} - -int32 Pet::GetTPForSpell(uint32 spellid) -{ - uint32 basetrainp = 0; - - SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellid); - SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellid); - for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) - { - if(!_spell_idx->second->reqtrainpoints) - return 0; - - basetrainp = _spell_idx->second->reqtrainpoints; - break; - } - - uint32 spenttrainp = 0; - uint32 chainstart = spellmgr.GetFirstSpellInChain(spellid); - - for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) - { - if(itr->second->state == PETSPELL_REMOVED) - continue; - - if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart) - { - SkillLineAbilityMap::const_iterator _lower = spellmgr.GetBeginSkillLineAbilityMap(itr->first); - SkillLineAbilityMap::const_iterator _upper = spellmgr.GetEndSkillLineAbilityMap(itr->first); - - for(SkillLineAbilityMap::const_iterator _spell_idx2 = _lower; _spell_idx2 != _upper; ++_spell_idx2) - { - if(_spell_idx2->second->reqtrainpoints > spenttrainp) - { - spenttrainp = _spell_idx2->second->reqtrainpoints; - break; - } - } - } - } - - return int32(basetrainp) - int32(spenttrainp); -} - -uint32 Pet::GetMaxLoyaltyPoints(uint32 level) -{ - return LevelUpLoyalty[level - 1]; -} - -uint32 Pet::GetStartLoyaltyPoints(uint32 level) -{ - return LevelStartLoyalty[level - 1]; -} - -void Pet::SetTP(int32 TP) -{ - m_TrainingPoints = TP; - SetUInt32Value(UNIT_TRAINING_POINTS, (uint32)GetDispTP()); -} - -int32 Pet::GetDispTP() -{ - if(getPetType()!= HUNTER_PET) - return(0); - if(m_TrainingPoints < 0) - return -m_TrainingPoints; - else - return -(m_TrainingPoints + 1); -} - void Pet::Remove(PetSaveMode mode, bool returnreagent) { Unit* owner = GetOwner(); @@ -895,7 +693,7 @@ void Pet::GivePetXP(uint32 xp) newXP -= nextLvlXP; SetLevel( level + 1 ); - SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((Trinity::XP::xp_to_level(level+1))/4)); + SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(level+1)/4); level = getLevel(); nextLvlXP = GetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP); @@ -903,9 +701,6 @@ void Pet::GivePetXP(uint32 xp) } SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, newXP); - - if(getPetType() == HUNTER_PET) - KillLoyaltyBonus(level); } void Pet::GivePetLevel(uint32 level) @@ -913,9 +708,8 @@ void Pet::GivePetLevel(uint32 level) if(!level) return; - InitStatsForLevel( level); - - SetTP(m_TrainingPoints + (GetLoyaltyLevel() - 1)); + InitStatsForLevel(level); + InitTalentForLevel(); } bool Pet::CreateBaseAtCreature(Creature* creature) @@ -932,7 +726,7 @@ bool Pet::CreateBaseAtCreature(Creature* creature) sLog.outDebug("Create pet"); uint32 pet_number = objmgr.GeneratePetNumber(); - if(!Create(guid, creature->GetMap(), creature->GetEntry(), pet_number)) + if(!Create(guid, creature->GetMap(), creature->GetPhaseMask(), creature->GetEntry(), pet_number)) return false; Relocate(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); @@ -963,26 +757,20 @@ bool Pet::CreateBaseAtCreature(Creature* creature) setPowerType(POWER_FOCUS); SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0); SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); - SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((Trinity::XP::xp_to_level(creature->getLevel()))/4)); - SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(creature->getLevel())/4); SetUInt32Value(UNIT_NPC_FLAGS, 0); - CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(creature->GetCreatureInfo()->family); - if( char* familyname = cFamily->Name[sWorld.GetDefaultDbcLocale()] ) - SetName(familyname); + if(CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family)) + SetName(cFamily->Name[sWorld.GetDefaultDbcLocale()]); else - SetName(creature->GetName()); + SetName(creature->GetNameForLocaleIdx(objmgr.GetDBCLocaleIndex())); - m_loyaltyPoints = 1000; if(cinfo->type == CREATURE_TYPE_BEAST) { SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 ); SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED); - - SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED) ); - SetLoyaltyLevel(REBELLIOUS); + SetUInt32Value(UNIT_MOD_CAST_SPEED, creature->GetUInt32Value(UNIT_MOD_CAST_SPEED)); } return true; } @@ -1111,8 +899,8 @@ bool Pet::InitStatsForLevel(uint32 petlevel) } case HUNTER_PET: { - SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((Trinity::XP::xp_to_level(petlevel))/4)); - + SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, objmgr.GetXPForLevel(petlevel)/4); + learnLevelupSpells(); //these formula may not be correct; however, it is designed to be close to what it should be //this makes dps 0.5 of pets level SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, float(petlevel - (petlevel / 4)) ); @@ -1304,7 +1092,7 @@ void Pet::_SaveSpellCooldowns() void Pet::_LoadSpells() { - QueryResult *result = CharacterDatabase.PQuery("SELECT spell,slot,active FROM pet_spell WHERE guid = '%u'",m_charmInfo->GetPetNumber()); + QueryResult *result = CharacterDatabase.PQuery("SELECT spell,active FROM pet_spell WHERE guid = '%u'",m_charmInfo->GetPetNumber()); if(result) { @@ -1312,7 +1100,7 @@ void Pet::_LoadSpells() { Field *fields = result->Fetch(); - addSpell(fields[0].GetUInt16(), fields[2].GetUInt16(), PETSPELL_UNCHANGED, fields[1].GetUInt16()); + addSpell(fields[0].GetUInt32(), fields[1].GetUInt16(), PETSPELL_UNCHANGED); } while( result->NextRow() ); @@ -1329,7 +1117,7 @@ void Pet::_SaveSpells() if (itr->second->state == PETSPELL_REMOVED || itr->second->state == PETSPELL_CHANGED) CharacterDatabase.PExecute("DELETE FROM pet_spell WHERE guid = '%u' and spell = '%u'", m_charmInfo->GetPetNumber(), itr->first); if (itr->second->state == PETSPELL_NEW || itr->second->state == PETSPELL_CHANGED) - CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,slot,active) VALUES ('%u', '%u', '%u','%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second->slotId,itr->second->active); + CharacterDatabase.PExecute("INSERT INTO pet_spell (guid,spell,active) VALUES ('%u', '%u', '%u')", m_charmInfo->GetPetNumber(), itr->first, itr->second->active); if (itr->second->state == PETSPELL_REMOVED) _removeSpell(itr->first); @@ -1344,10 +1132,6 @@ void Pet::_LoadAuras(uint32 timediff) for (int i = 0; i < TOTAL_AURAS; i++) m_modAuras[i].clear(); - // all aura related fields - for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i) - SetUInt32Value(i, 0); - QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber()); if(result) @@ -1451,7 +1235,7 @@ void Pet::_SaveAuras() { CharacterDatabase.PExecute("INSERT INTO pet_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) " "VALUES ('%u', '" I64FMTD "', '%u', '%u', '%u', '%d', '%d', '%d', '%d')", - m_charmInfo->GetPetNumber(), itr2->second->GetCasterGUID(),(uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), (uint32)itr2->second->GetStackAmount(), itr2->second->GetModifier()->m_amount,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->m_procCharges)); + m_charmInfo->GetPetNumber(), itr2->second->GetCasterGUID(),(uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), (uint32)itr2->second->GetStackAmount(), itr2->second->GetModifier()->m_amount ,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->GetAuraCharges())); } } } @@ -1469,7 +1253,7 @@ void Pet::_SaveAuras() } } -bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 slot_id, PetSpellType type) +bool Pet::addSpell(uint32 spell_id, uint16 active, PetSpellState state, PetSpellType type) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); if (!spellInfo) @@ -1488,7 +1272,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s // same spells don't have autocast option if (spellInfo->AttributesEx & SPELL_ATTR_EX_UNAUTOCASTABLE_BY_PET) - active = ACT_CAST; + active = ACT_ENABLED; PetSpellMap::iterator itr = m_spells.find(spell_id); if (itr != m_spells.end()) @@ -1525,40 +1309,45 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s else newspell->active = active; - uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id); - - for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) + // talent: unlearn all other talent ranks (high and low) + if(TalentSpellPos const* talentPos = GetTalentSpellPos(spell_id)) { - if(itr->second->state == PETSPELL_REMOVED) continue; - - if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart) + if(TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentPos->talent_id )) { - slot_id = itr->second->slotId; - newspell->active = itr->second->active; - - if(newspell->active == ACT_ENABLED) - ToggleAutocast(itr->first, false); + for(int i=0; i <5; ++i) + { + // skip learning spell and no rank spell case + uint32 rankSpellId = talentInfo->RankID[i]; + if(!rankSpellId || rankSpellId==spell_id) + continue; - oldspell_id = itr->first; - removeSpell(itr->first); + // skip unknown ranks + if(!HasSpell(rankSpellId)) + continue; + removeSpell(rankSpellId); + } } } - - uint16 tmpslot=slot_id; - - if (tmpslot == 0xffff) + else if(uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id)) { - uint16 maxid = 0; - PetSpellMap::iterator itr; - for (itr = m_spells.begin(); itr != m_spells.end(); ++itr) + for (PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) { if(itr->second->state == PETSPELL_REMOVED) continue; - if (itr->second->slotId > maxid) maxid = itr->second->slotId; + + if(spellmgr.GetFirstSpellInChain(itr->first) == chainstart) + { + newspell->active = itr->second->active; + + if(newspell->active == ACT_ENABLED) + ToggleAutocast(itr->first, false); + + oldspell_id = itr->first; + unlearnSpell(itr->first); + break; + } } - tmpslot = maxid + 1; } - newspell->slotId = tmpslot; m_spells[spell_id] = newspell; if (IsPassiveSpell(spell_id)) @@ -1569,29 +1358,81 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s if(newspell->active == ACT_ENABLED) ToggleAutocast(spell_id, true); + uint32 talentCost = GetTalentSpellCost(spell_id); + if (talentCost) + { + int32 free_points = GetMaxTalentPointsForLevel(getLevel()); + m_usedTalentCount+=talentCost; + // update free talent points + free_points-=m_usedTalentCount; + SetFreeTalentPoints(free_points > 0 ? free_points : 0); + } return true; } -bool Pet::learnSpell(uint16 spell_id) +bool Pet::learnSpell(uint32 spell_id) { // prevent duplicated entires in spell book if (!addSpell(spell_id)) return false; Unit* owner = GetOwner(); - if(owner->GetTypeId()==TYPEID_PLAYER) + if(owner && owner->GetTypeId() == TYPEID_PLAYER) + { + if(!m_loading) + { + WorldPacket data(SMSG_PET_LEARNED_SPELL, 2); + data << uint16(spell_id); + ((Player*)owner)->GetSession()->SendPacket(&data); + } ((Player*)owner)->PetSpellInitialize(); + } return true; } -void Pet::removeSpell(uint16 spell_id) +void Pet::learnLevelupSpells() +{ + PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family); + if(!levelupSpells) + return; + + uint32 level = getLevel(); + + for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr) + { + if(itr->first <= level) + learnSpell(itr->second); + else + unlearnSpell(itr->second); + } +} + +bool Pet::unlearnSpell(uint32 spell_id) +{ + if(removeSpell(spell_id)) + { + if(GetOwner()->GetTypeId() == TYPEID_PLAYER) + { + if(!m_loading) + { + WorldPacket data(SMSG_PET_REMOVED_SPELL, 2); + data << uint16(spell_id); + ((Player*)GetOwner())->GetSession()->SendPacket(&data); + } + } + return true; + } + return false; +} + +bool Pet::removeSpell(uint32 spell_id) { PetSpellMap::iterator itr = m_spells.find(spell_id); if (itr == m_spells.end()) - return; + return false; if(itr->second->state == PETSPELL_REMOVED) - return; + return false; if(itr->second->state == PETSPELL_NEW) { @@ -1602,9 +1443,23 @@ void Pet::removeSpell(uint16 spell_id) itr->second->state = PETSPELL_REMOVED; RemoveAurasDueToSpell(spell_id); + + uint32 talentCost = GetTalentSpellCost(spell_id); + if (talentCost > 0) + { + if (m_usedTalentCount > talentCost) + m_usedTalentCount-=talentCost; + else + m_usedTalentCount = 0; + // update free talent points + int32 free_points = GetMaxTalentPointsForLevel(getLevel()) - m_usedTalentCount; + SetFreeTalentPoints(free_points > 0 ? free_points : 0); + } + + return true; } -bool Pet::_removeSpell(uint16 spell_id) +bool Pet::_removeSpell(uint32 spell_id) { PetSpellMap::iterator itr = m_spells.find(spell_id); if (itr != m_spells.end()) @@ -1620,8 +1475,11 @@ void Pet::InitPetCreateSpells() { m_charmInfo->InitPetActionBar(); + for (PetSpellMap::iterator i = m_spells.begin(); i != m_spells.end(); ++i) + delete i->second; m_spells.clear(); - int32 usedtrainpoints = 0, petspellid; + + uint32 petspellid; PetCreateSpellEntry const* CreateSpells = objmgr.GetPetCreateSpellEntry(GetEntry()); if(CreateSpells) { @@ -1641,7 +1499,7 @@ void Pet::InitPetCreateSpells() if(owner->GetTypeId() == TYPEID_PLAYER && !((Player*)owner)->HasSpell(learn_spellproto->Id)) { if(IsPassiveSpell(petspellid)) //learn passive skills when tamed, not sure if thats right - ((Player*)owner)->learnSpell(learn_spellproto->Id); + ((Player*)owner)->learnSpell(learn_spellproto->Id,false); else AddTeachSpell(learn_spellproto->EffectTriggerSpell[0], learn_spellproto->Id); } @@ -1650,23 +1508,12 @@ void Pet::InitPetCreateSpells() petspellid = learn_spellproto->Id; addSpell(petspellid); - - SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]); - SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(learn_spellproto->EffectTriggerSpell[0]); - - for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) - { - usedtrainpoints += _spell_idx->second->reqtrainpoints; - break; - } } } LearnPetPassives(); CastPetAuras(false); - - SetTP(-usedtrainpoints); } void Pet::CheckLearning(uint32 spellid) @@ -1686,11 +1533,115 @@ void Pet::CheckLearning(uint32 spellid) if(urand(0, 100) < 10) { - ((Player*)owner)->learnSpell(itr->second); + ((Player*)owner)->learnSpell(itr->second,false); m_teachspells.erase(itr); } } +bool Pet::resetTalents(bool no_cost) +{ + Unit *owner = GetOwner(); + if (!owner || owner->GetTypeId()!=TYPEID_PLAYER) + return false; + + CreatureInfo const * ci = GetCreatureInfo(); + if(!ci) + return false; + // Check pet talent type + CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); + if(!pet_family || pet_family->petTalentType < 0) + return false; + + Player *player = (Player *)owner; + + uint32 level = getLevel(); + uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level); + + if (m_usedTalentCount == 0) + { + SetFreeTalentPoints(talentPointsForLevel); + return false; + } + + uint32 cost = 0; + + if(!no_cost) + { + cost = resetTalentsCost(); + + if (player->GetMoney() < cost) + { + player->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); + return false; + } + } + + for (unsigned int i = 0; i < sTalentStore.GetNumRows(); i++) + { + TalentEntry const *talentInfo = sTalentStore.LookupEntry(i); + + if (!talentInfo) continue; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab ); + + if(!talentTabInfo) + continue; + + // unlearn only talents for pets family talent type + if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask)) + continue; + + for (int j = 0; j < 5; j++) + { + for(PetSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end();) + { + if(itr->second->state == PETSPELL_REMOVED) + { + ++itr; + continue; + } + // remove learned spells (all ranks) + uint32 itrFirstId = spellmgr.GetFirstSpellInChain(itr->first); + + // unlearn if first rank is talent or learned by talent + if (itrFirstId == talentInfo->RankID[j] || spellmgr.IsSpellLearnToSpell(talentInfo->RankID[j],itrFirstId)) + { + removeSpell(itr->first); + itr = m_spells.begin(); + continue; + } + else + ++itr; + } + } + } + + SetFreeTalentPoints(talentPointsForLevel); + + if(!no_cost) + { + player->ModifyMoney(-(int32)cost); + + m_resetTalentsCost = cost; + m_resetTalentsTime = time(NULL); + } + player->PetSpellInitialize(); + return true; +} + +void Pet::InitTalentForLevel() +{ + uint32 level = getLevel(); + uint32 talentPointsForLevel = GetMaxTalentPointsForLevel(level); + // Reset talents in case low level (on level down) or wrong points for level (hunter can unlearn TP increase talent) + if(talentPointsForLevel == 0 || m_usedTalentCount > talentPointsForLevel) + { + // Remove all talent points + resetTalents(true); + } + SetFreeTalentPoints(talentPointsForLevel - m_usedTalentCount); +} + uint32 Pet::resetTalentsCost() const { uint32 days = (sWorld.GetGameTime() - m_resetTalentsTime)/DAY; @@ -1709,6 +1660,15 @@ uint32 Pet::resetTalentsCost() const return (m_resetTalentsCost + 1*GOLD > 10*GOLD ? 10*GOLD : m_resetTalentsCost + 1*GOLD); } +uint8 Pet::GetMaxTalentPointsForLevel(uint32 level) +{ + uint8 points = (level >= 20) ? ((level - 16) / 4) : 0; + // Mod points from owner SPELL_AURA_MOD_PET_TALENT_POINTS + if (Unit *owner = GetOwner()) + points+=owner->GetTotalAuraModifier(SPELL_AURA_MOD_PET_TALENT_POINTS); + return points; +} + void Pet::ToggleAutocast(uint32 spellid, bool apply) { if(IsPassiveSpell(spellid)) @@ -1719,13 +1679,15 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) // && tempSpell->EffectImplicitTargetA[0] != TARGET_CHAIN_DAMAGE) // return; - PetSpellMap::const_iterator itr = m_spells.find((uint16)spellid); + PetSpellMap::const_iterator itr = m_spells.find(spellid); int i; if(apply) { - for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++); + for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++) + ; // just search + if (i == m_autospells.size()) { m_autospells.push_back(spellid); @@ -1736,7 +1698,9 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) else { AutoSpellList::iterator itr2 = m_autospells.begin(); - for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++); + for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++) + ; // just search + if (i < m_autospells.size()) { m_autospells.erase(itr2); @@ -1746,10 +1710,11 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) } } -bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number) +bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number) { SetMapId(map->GetId()); SetInstanceId(map->GetInstanceId()); + SetPhaseMask(phaseMask,false); Object::_Create(guidlow, pet_number, HIGHGUID_PET); @@ -1759,8 +1724,7 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number) if(!InitEntry(Entry)) return false; - SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_AURAS | UNIT_BYTE2_FLAG_UNK5 ); + SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); if(getPetType() == MINI_PET) // always non-attackable SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); @@ -1770,7 +1734,8 @@ bool Pet::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number) bool Pet::HasSpell(uint32 spell) const { - return (m_spells.find(spell) != m_spells.end()); + PetSpellMap::const_iterator itr = m_spells.find(spell); + return (itr != m_spells.end() && itr->second->state != PETSPELL_REMOVED ); } // Get all passive spells in our skill line @@ -1791,7 +1756,7 @@ void Pet::LearnPetPassives() // Passive 01~10, Passive 00 (20782, not used), Ferocious Inspiration (34457) // Scale 01~03 (34902~34904, bonus from owner, not used) for(PetFamilySpellsSet::const_iterator petSet = petStore->second.begin(); petSet != petStore->second.end(); ++petSet) - addSpell(*petSet, ACT_DECIDE, PETSPELL_NEW, 0xffff, PETSPELL_FAMILY); + addSpell(*petSet, ACT_DECIDE, PETSPELL_NEW, PETSPELL_FAMILY); } } diff --git a/src/game/Pet.h b/src/game/Pet.h index 9d187b24b45..f863051b74d 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -52,16 +52,6 @@ enum HappinessState HAPPY = 3 }; -enum LoyaltyLevel -{ - REBELLIOUS = 1, - UNRULY = 2, - SUBMISSIVE = 3, - DEPENDABLE = 4, - FAITHFUL = 5, - BEST_FRIEND = 6 -}; - enum PetSpellState { PETSPELL_UNCHANGED = 0, @@ -78,7 +68,6 @@ enum PetSpellType struct PetSpell { - uint16 slotId; uint16 active; PetSpellState state : 16; @@ -116,15 +105,12 @@ enum PetNameInvalidReason PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 16 }; -typedef UNORDERED_MAP<uint16, PetSpell*> PetSpellMap; +typedef UNORDERED_MAP<uint32, PetSpell*> PetSpellMap; typedef std::map<uint32,uint32> TeachSpellMap; typedef std::vector<uint32> AutoSpellList; #define HAPPINESS_LEVEL_SIZE 333000 -extern const uint32 LevelUpLoyalty[6]; -extern const uint32 LevelStartLoyalty[6]; - #define ACTIVE_SPELLS_MAX 4 #define OWNER_MAX_DISTANCE 100 @@ -146,9 +132,9 @@ class Pet : public Creature bool isControlled() const { return getPetType()==SUMMON_PET || getPetType()==HUNTER_PET; } bool isTemporarySummoned() const { return m_duration > 0; } - bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 pet_number); + bool Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number); bool CreateBaseAtCreature(Creature* creature); - bool LoadPetFromDB( Unit* owner,uint32 petentry = 0,uint32 petnumber = 0, bool current = false ); + bool LoadPetFromDB( Player* owner,uint32 petentry = 0,uint32 petnumber = 0, bool current = false ); void SavePetToDB(PetSaveMode mode); void Remove(PetSaveMode mode, bool returnreagent = false); static void DeleteFromDB(uint32 guidlow); @@ -167,14 +153,7 @@ class Pet : public Creature void RegenerateFocus(); void LooseHappiness(); - void TickLoyaltyChange(); - void ModifyLoyalty(int32 addvalue); HappinessState GetHappinessState(); - uint32 GetMaxLoyaltyPoints(uint32 level); - uint32 GetStartLoyaltyPoints(uint32 level); - void KillLoyaltyBonus(uint32 level); - uint32 GetLoyaltyLevel() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); } - void SetLoyaltyLevel(LoyaltyLevel level); void GivePetXP(uint32 xp); void GivePetLevel(uint32 level); bool InitStatsForLevel(uint32 level); @@ -194,10 +173,8 @@ class Pet : public Creature void UpdateAttackPowerAndDamage(bool ranged = false); void UpdateDamagePhysical(WeaponAttackType attType); - bool CanTakeMoreActiveSpells(uint32 SpellIconID); - void ToggleAutocast(uint32 spellid, bool apply); - bool HasTPForSpell(uint32 spellid); - int32 GetTPForSpell(uint32 spellid); + bool CanTakeMoreActiveSpells(uint32 SpellIconID); + void ToggleAutocast(uint32 spellid, bool apply); bool HasSpell(uint32 spell) const; void AddTeachSpell(uint32 learned_id, uint32 source_id) { m_teachspells[learned_id] = source_id; } @@ -213,10 +190,12 @@ class Pet : public Creature void _LoadSpells(); void _SaveSpells(); - bool addSpell(uint16 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, uint16 slot_id=0xffff, PetSpellType type = PETSPELL_NORMAL); - bool learnSpell(uint16 spell_id); - void removeSpell(uint16 spell_id); - bool _removeSpell(uint16 spell_id); + bool addSpell(uint32 spell_id,uint16 active = ACT_DECIDE, PetSpellState state = PETSPELL_NEW, PetSpellType type = PETSPELL_NORMAL); + bool learnSpell(uint32 spell_id); + void learnLevelupSpells(); + bool unlearnSpell(uint32 spell_id); + bool removeSpell(uint32 spell_id); + bool _removeSpell(uint32 spell_id); PetSpellMap m_spells; TeachSpellMap m_teachspells; @@ -224,32 +203,33 @@ class Pet : public Creature void InitPetCreateSpells(); void CheckLearning(uint32 spellid); + + bool resetTalents(bool no_cost = false); uint32 resetTalentsCost() const; + void InitTalentForLevel(); - void SetTP(int32 TP); - int32 GetDispTP(); + uint8 GetMaxTalentPointsForLevel(uint32 level); + uint8 GetFreeTalentPoints() { return GetByteValue(UNIT_FIELD_BYTES_1, 1); } + void SetFreeTalentPoints(uint8 points) { SetByteValue(UNIT_FIELD_BYTES_1, 1, points); } - int32 m_TrainingPoints; uint32 m_resetTalentsCost; time_t m_resetTalentsTime; + uint32 m_usedTalentCount; - uint64 GetAuraUpdateMask() { return m_auraUpdateMask; } - void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } - void UnsetAuraUpdateMask(uint8 slot) { m_auraUpdateMask &= ~(uint64(1) << slot); } - void ResetAuraUpdateMask() { m_auraUpdateMask = 0; } + const uint64& GetAuraUpdateMaskForRaid() const { return m_auraRaidUpdateMask; } + void SetAuraUpdateMaskForRaid(uint8 slot) { m_auraRaidUpdateMask |= (uint64(1) << slot); } + void ResetAuraUpdateMaskForRaid() { m_auraRaidUpdateMask = 0; } DeclinedName const* GetDeclinedNames() const { return m_declinedname; } bool m_removed; // prevent overwrite pet state in DB at next Pet::Update if pet already removed(saved) protected: - uint32 m_regenTimer; uint32 m_happinessTimer; - uint32 m_loyaltyTimer; PetType m_petType; int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets) - int32 m_loyaltyPoints; int32 m_bonusdamage; - uint64 m_auraUpdateMask; + uint64 m_auraRaidUpdateMask; + bool m_loading; DeclinedName *m_declinedname; diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 67607defba0..4545b9a395f 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -139,11 +139,11 @@ void PetAI::UpdateAI(const uint32 diff) else m_updateAlliesTimer -= diff; - if (inCombat && i_pet.getVictim() == NULL) + if (inCombat && !i_pet.getVictim()) _stopAttack(); // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. - if( i_pet.getVictim() != NULL ) + if( i_pet.getVictim() ) { if( _needToStop() ) { diff --git a/src/game/PetAI.h b/src/game/PetAI.h index b81bdd8e14f..ceaa00e7ed3 100644 --- a/src/game/PetAI.h +++ b/src/game/PetAI.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index e4269ddafd6..da8ce311462 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -106,7 +106,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) } // only place where pet can be player pet->clearUnitState(UNIT_STAT_FOLLOW); - uint64 selguid = _player->GetSelection(); + const uint64& selguid = _player->GetSelection(); Unit *TargetUnit = ObjectAccessor::GetUnit(*_player, selguid); if(!TargetUnit) return; @@ -118,27 +118,35 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) //if(!pet->IsWithinLOSInMap(TargetUnit)) // return; - if(pet->GetTypeId() != TYPEID_PLAYER) + // This is true if pet has no target or has target but targets differs. + if(pet->getVictim() != TargetUnit) { - if (((Creature*)pet)->AI()) - ((Creature*)pet)->AI()->AttackStart(TargetUnit); + if (pet->getVictim()) + pet->AttackStop(); - //10% chance to play special pet attack talk, else growl - if(((Creature*)pet)->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) - pet->SendPetTalk((uint32)PET_TALK_ATTACK); - else + if(pet->GetTypeId() != TYPEID_PLAYER) { - // 90% chance for pet and 100% chance for charmed creature - pet->SendPetAIReaction(guid1); + pet->GetMotionMaster()->Clear(); + if (((Creature*)pet)->AI()) + ((Creature*)pet)->AI()->AttackStart(TargetUnit); + + //10% chance to play special pet attack talk, else growl + if(((Creature*)pet)->isPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) + pet->SendPetTalk((uint32)PET_TALK_ATTACK); + else + { + // 90% chance for pet and 100% chance for charmed creature + pet->SendPetAIReaction(guid1); + } } - } - else // charmed player - { - if(pet->getVictim() && pet->getVictim() != TargetUnit) - pet->AttackStop(); + else // charmed player + { + if(pet->getVictim() && pet->getVictim() != TargetUnit) + pet->AttackStop(); - pet->Attack(TargetUnit,true); - pet->SendPetAIReaction(guid1); + pet->Attack(TargetUnit,true); + pet->SendPetAIReaction(guid1); + } } break; } @@ -174,19 +182,17 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) break; } break; - case ACT_DISABLED: //0x8100 spell (disabled), ignore - case ACT_CAST: //0x0100 - case ACT_ENABLED: //0xc100 spell + case ACT_DISABLED: // 0x8100 spell (disabled), ignore + case ACT_PASSIVE: // 0x0100 + case ACT_ENABLED: // 0xC100 spell { - Unit* unit_target; - if(guid2) - unit_target = ObjectAccessor::GetUnit(*_player,guid2); - else - unit_target = NULL; - + Unit* unit_target = NULL; if (((Creature*)pet)->GetGlobalCooldown() > 0) return; + if(guid2) + unit_target = ObjectAccessor::GetUnit(*_player,guid2); + // do not cast unknown spells SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid ); if(!spellInfo) @@ -211,7 +217,7 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) int16 result = spell->PetCanCast(unit_target); - //auto turn to target unless possessed + //auto turn to target unless possessed if(result == SPELL_FAILED_UNIT_NOT_INFRONT && !pet->isPossessed()) { pet->SetInFront(unit_target); @@ -242,12 +248,15 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) if( unit_target && !GetPlayer()->IsFriendlyTo(unit_target) && !pet->isPossessed()) { - pet->clearUnitState(UNIT_STAT_FOLLOW); - if(pet->getVictim()) - pet->AttackStop(); - pet->GetMotionMaster()->Clear(); - if (((Creature*)pet)->AI()) - ((Creature*)pet)->AI()->AttackStart(unit_target); + // This is true if pet has no target or has target but targets differs. + if (pet->getVictim() != unit_target) + { + if (pet->getVictim()) + pet->AttackStop(); + pet->GetMotionMaster()->Clear(); + if (((Creature*)pet)->AI()) + ((Creature*)pet)->AI()->AttackStart(unit_target); + } } spell->prepare(&(spell->m_targets)); @@ -257,15 +266,12 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) if(pet->isPossessed()) { WorldPacket data(SMSG_CAST_FAILED, (4+1+1)); - data << uint32(spellid) << uint8(2) << uint8(result); + data << uint8(0) << uint32(spellid) << uint8(result); switch (result) { case SPELL_FAILED_REQUIRES_SPELL_FOCUS: data << uint32(spellInfo->RequiresSpellFocus); break; - case SPELL_FAILED_REQUIRES_AREA: - data << uint32(spellInfo->AreaId); - break; } SendPacket(&data); } @@ -302,7 +308,7 @@ void WorldSession::HandlePetNameQuery( WorldPacket & recv_data ) void WorldSession::SendPetNameQuery( uint64 petguid, uint32 petnumber) { - Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, petguid); + Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid); if(!pet || !pet->GetCharmInfo() || pet->GetCharmInfo()->GetPetNumber() != petnumber) return; @@ -344,7 +350,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) if(ObjectAccessor::FindPlayer(petguid)) return; - Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, petguid); + Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, petguid); if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) { @@ -369,7 +375,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X\n", _player->GetName(), position, spell_id, act_state); //if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add - if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_CAST) && spell_id && !pet->HasSpell(spell_id))) + if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id))) { //sign for autocast if(act_state == ACT_ENABLED && spell_id) @@ -481,7 +487,7 @@ void WorldSession::HandlePetAbandon( WorldPacket & recv_data ) sLog.outDetail( "HandlePetAbandon. CMSG_PET_ABANDON pet guid is %u", GUID_LOPART(guid) ); // pet/charmed - Creature* pet = ObjectAccessor::GetCreatureOrPet(*_player, guid); + Creature* pet = ObjectAccessor::GetCreatureOrPetOrVehicle(*_player, guid); if(pet) { if(pet->isPet()) @@ -510,11 +516,11 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) sLog.outDetail("CMSG_PET_UNLEARN"); uint64 guid; - recvPacket >> guid; + recvPacket >> guid; // Pet guid Pet* pet = _player->GetPet(); - if(!pet || pet->getPetType() != HUNTER_PET || pet->m_spells.size() <= 1) + if(!pet || pet->getPetType() != HUNTER_PET || pet->m_usedTalentCount == 0) return; if(guid != pet->GetGUID()) @@ -529,38 +535,7 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) sLog.outError("WorldSession::HandlePetUnlearnOpcode: object "I64FMTD" is considered pet-like but doesn't have a charminfo!", pet->GetGUID()); return; } - - uint32 cost = pet->resetTalentsCost(); - - if (GetPlayer()->GetMoney() < cost) - { - GetPlayer()->SendBuyError( BUY_ERR_NOT_ENOUGHT_MONEY, 0, 0, 0); - return; - } - - for(PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end();) - { - uint32 spell_id = itr->first; // Pet::removeSpell can invalidate iterator at erase NEW spell - ++itr; - pet->removeSpell(spell_id); - } - - pet->SetTP(pet->getLevel() * (pet->GetLoyaltyLevel() - 1)); - - for(uint8 i = 0; i < 10; i++) - { - if(charmInfo->GetActionBarEntry(i)->SpellOrAction && charmInfo->GetActionBarEntry(i)->Type == ACT_ENABLED || charmInfo->GetActionBarEntry(i)->Type == ACT_DISABLED) - charmInfo->GetActionBarEntry(i)->SpellOrAction = 0; - } - - // relearn pet passives - pet->LearnPetPassives(); - - pet->m_resetTalentsTime = time(NULL); - pet->m_resetTalentsCost = cost; - GetPlayer()->ModifyMoney(-(int32)cost); - - GetPlayer()->PetSpellInitialize(); + pet->resetTalents(); } void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) @@ -580,7 +555,7 @@ void WorldSession::HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ) if(ObjectAccessor::FindPlayer(guid)) return; - Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid); + Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid); if(!pet || (pet != _player->GetPet() && pet != _player->GetCharm())) { @@ -616,11 +591,15 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) { sLog.outDetail("WORLD: CMSG_PET_CAST_SPELL"); - CHECK_PACKET_SIZE(recvPacket,8+4); + CHECK_PACKET_SIZE(recvPacket,8+1+4+1); uint64 guid; uint32 spellid; + uint8 cast_count; + uint8 unk_flags; // flags (if 0x02 - some additional data are received) + + recvPacket >> guid >> cast_count >> spellid >> unk_flags; - recvPacket >> guid >> spellid; + sLog.outDebug("WORLD: CMSG_PET_CAST_SPELL, cast_count: %u, spellid %u, unk_flags %u", cast_count, spellid, unk_flags); // This opcode is also sent from charmed and possessed units (players and creatures) if(!_player->GetPet() && !_player->GetCharm()) @@ -655,6 +634,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) caster->clearUnitState(UNIT_STAT_FOLLOW); Spell *spell = new Spell(caster, spellInfo, false); + spell->m_cast_count = cast_count; // probably pending spell cast spell->m_targets = targets; int16 result = spell->PetCanCast(NULL); @@ -713,3 +693,129 @@ void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, Dec data << uint8(0); SendPacket(&data); } + +void WorldSession::HandlePetLearnTalent( WorldPacket & recv_data ) +{ + sLog.outDebug("WORLD: CMSG_PET_LEARN_TALENT"); + recv_data.hexlike(); + + CHECK_PACKET_SIZE(recv_data, 8+4+4); + + uint64 guid; + uint32 talent_id, requested_rank; + recv_data >> guid >> talent_id >> requested_rank; + + Pet *pet = _player->GetPet(); + + if(!pet) + return; + + if(guid != pet->GetGUID()) + return; + + uint32 CurTalentPoints = pet->GetFreeTalentPoints(); + + if(CurTalentPoints == 0) + return; + + if (requested_rank > 4) + return; + + TalentEntry const *talentInfo = sTalentStore.LookupEntry(talent_id); + + if(!talentInfo) + return; + + TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab); + + if(!talentTabInfo) + return; + + CreatureInfo const *ci = pet->GetCreatureInfo(); + + if(!ci) + return; + + CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(ci->family); + + if(!pet_family) + return; + + if(pet_family->petTalentType < 0) // not hunter pet + return; + + // prevent learn talent for different family (cheating) + if(!((1 << pet_family->petTalentType) & talentTabInfo->petTalentMask)) + return; + + // prevent skip talent ranks (cheating) + if(requested_rank > 0 && !pet->HasSpell(talentInfo->RankID[requested_rank-1])) + return; + + // Check if it requires another talent + if (talentInfo->DependsOn > 0) + { + if(TalentEntry const *depTalentInfo = sTalentStore.LookupEntry(talentInfo->DependsOn)) + { + bool hasEnoughRank = false; + for (int i = talentInfo->DependsOnRank; i <= 4; i++) + { + if (depTalentInfo->RankID[i] != 0) + if (pet->HasSpell(depTalentInfo->RankID[i])) + hasEnoughRank = true; + } + if (!hasEnoughRank) + return; + } + } + + // Find out how many points we have in this field + uint32 spentPoints = 0; + + uint32 tTab = talentInfo->TalentTab; + if (talentInfo->Row > 0) + { + unsigned int numRows = sTalentStore.GetNumRows(); + for (unsigned int i = 0; i < numRows; i++) // Loop through all talents. + { + // Someday, someone needs to revamp + const TalentEntry *tmpTalent = sTalentStore.LookupEntry(i); + if (tmpTalent) // the way talents are tracked + { + if (tmpTalent->TalentTab == tTab) + { + for (int j = 0; j <= 4; j++) + { + if (tmpTalent->RankID[j] != 0) + { + if (pet->HasSpell(tmpTalent->RankID[j])) + { + spentPoints += j + 1; + } + } + } + } + } + } + } + + // not have required min points spent in talent tree + if(spentPoints < (talentInfo->Row * 3)) + return; + + // spell not set in talent.dbc + uint32 spellid = talentInfo->RankID[requested_rank]; + if( spellid == 0 ) + { + sLog.outError("Talent.dbc have for talent: %u Rank: %u spell id = 0", talent_id, requested_rank); + return; + } + + // already known + if(pet->HasSpell(spellid)) + return; + + // learn! (other talent ranks will unlearned at learning) + pet->learnSpell(spellid); + sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid); +} diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index 8fc18b1c259..5911af4e560 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -199,9 +199,9 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) if(!charter) return; - charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT, charter->GetGUIDLow()); - // ITEM_FIELD_ENCHANTMENT is guild/arenateam id - // ITEM_FIELD_ENCHANTMENT+1 is current signatures count (showed on item) + charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow()); + // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id + // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item) charter->SetState(ITEM_CHANGED, _player); _player->SendNewItem(charter, 1, true, false); @@ -565,7 +565,7 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) // update signs count on charter, required testing... //Item *item = _player->GetItemByGuid(petitionguid)); //if(item) - // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+1, signs); + // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs); // update for owner if online if(Player *owner = objmgr.GetPlayer(ownerguid)) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 02e6e94f94c..2dba5867129 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -64,6 +64,7 @@ #include "Spell.h" #include "SocialMgr.h" #include "GameEvent.h" +#include "AchievementMgr.h" #include <cmath> @@ -132,7 +133,7 @@ PlayerTaxi::PlayerTaxi() memset(m_taximask, 0, sizeof(m_taximask)); } -void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 level) +void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint32 level) { // capital and taxi hub masks switch(race) @@ -149,6 +150,13 @@ void PlayerTaxi::InitTaxiNodesForLevel(uint32 race, uint32 level) case RACE_BLOODELF: SetTaximaskNode(82); break; // Blood Elf case RACE_DRAENEI: SetTaximaskNode(94); break; // Draenei } + + switch(chrClass) + { + case CLASS_DEATH_KNIGHT: // TODO: figure out initial known nodes + break; + } + // new continent starting masks (It will be accessible only at new map) switch(Player::TeamForRace(race)) { @@ -188,7 +196,7 @@ void PlayerTaxi::AppendTaximaskTo( ByteBuffer& data, bool all ) } } -bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values ) +bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values, uint32 team ) { ClearTaxiDestinations(); @@ -216,6 +224,10 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values ) return false; } + // can't load taxi path without mount set (quest taxi path?) + if(!objmgr.GetTaxiMount(GetTaxiSource(),team)) + return false; + return true; } @@ -245,13 +257,22 @@ uint32 PlayerTaxi::GetCurrentTaxiPath() const return path; } +std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi) +{ + ss << "'"; + for(int i = 0; i < TaxiMaskSize; ++i) + ss << taxi.m_taximask[i] << " "; + ss << "'"; + return ss; +} + //== Player ==================================================== const int32 Player::ReputationRank_Length[MAX_REPUTATION_RANK] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000}; UpdateMask Player::updateVisualBits; -Player::Player (WorldSession *session): Unit() +Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) { m_transport = 0; @@ -280,6 +301,7 @@ Player::Player (WorldSession *session): Unit() m_comboPoints = 0; m_usedTalentCount = 0; + m_questRewardTalentCount = 0; m_regenTimer = 0; m_weaponChangeTimer = 0; @@ -306,7 +328,7 @@ Player::Player (WorldSession *session): Unit() // group is initialized in the reference constructor SetGroupInvite(NULL); m_groupUpdateMask = 0; - m_auraUpdateMask = 0; + m_auraRaidUpdateMask = 0; duel = NULL; @@ -335,7 +357,7 @@ Player::Player (WorldSession *session): Unit() m_regenTimer = 0; m_weaponChangeTimer = 0; m_breathTimer = 0; - m_isunderwater = 0; + m_isunderwater = UNDERWATER_NONE; m_isInWater = false; m_drunkTimer = 0; m_drunk = 0; @@ -362,6 +384,7 @@ Player::Player (WorldSession *session): Unit() m_canParry = false; m_canBlock = false; m_canDualWield = false; + m_canTitanGrip = false; m_ammoDPS = 0.0f; m_temporaryUnsummonedPetNumber = 0; @@ -406,6 +429,14 @@ Player::Player (WorldSession *session): Unit() m_auraBaseMod[i][PCT_MOD] = 1.0f; } + for (int i = 0; i < MAX_COMBAT_RATING; i++) + m_baseRatingValue[i] = 0; + + m_baseSpellDamage = 0; + m_baseSpellHealing = 0; + m_baseFeralAP = 0; + m_baseManaRegen = 0; + // Honor System m_lastHonorUpdateTime = time(NULL); @@ -419,6 +450,8 @@ Player::Player (WorldSession *session): Unit() //Default movement to run mode m_unit_movement_flags = 0; + m_mover = NULL; + m_miniPet = 0; m_bgAfkReportedTimer = 0; m_contestedPvPTimer = 0; @@ -428,6 +461,8 @@ Player::Player (WorldSession *session): Unit() m_isActive = true; m_farsightVision = false; + + m_runes = NULL; } Player::~Player () @@ -475,6 +510,7 @@ Player::~Player () RemovePossess(false); delete m_declinedname; + delete m_runes; } void Player::CleanupsBeforeDelete() @@ -520,24 +556,8 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 uint8 powertype = cEntry->powerType; - uint32 unitfield; - - switch(powertype) - { - case POWER_ENERGY: - case POWER_MANA: - unitfield = 0x00000000; - break; - case POWER_RAGE: - unitfield = 0x00110000; - break; - default: - sLog.outError("Invalid default powertype %u for player (class %u)",powertype,class_); - return false; - } - - SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE ); - SetFloatValue(UNIT_FIELD_COMBATREACH, DEFAULT_COMBAT_REACH ); + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); + SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f); switch(gender) { @@ -560,12 +580,13 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 uint32 RaceClassGender = ( race ) | ( class_ << 8 ) | ( gender << 16 ); SetUInt32Value(UNIT_FIELD_BYTES_0, ( RaceClassGender | ( powertype << 24 ) ) ); - SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY | UNIT_BYTE2_FLAG_UNK5 ); - SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); + SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP ); + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); + SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER); SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); // fix cast time showed in spell tooltip on client + SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); // default for players in 3.0.3 - //-1 is default value + // -1 is default value SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); SetUInt32Value(PLAYER_BYTES, (skin | (face << 8) | (hairStyle << 16) | (hairColor << 24))); @@ -577,6 +598,7 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 SetUInt32Value( PLAYER_GUILD_TIMESTAMP, 0 ); SetUInt64Value( PLAYER__FIELD_KNOWN_TITLES, 0 ); // 0=disabled + SetUInt64Value( PLAYER__FIELD_KNOWN_TITLES1, 0 ); // 0=disabled SetUInt32Value( PLAYER_CHOSEN_TITLE, 0 ); SetUInt32Value( PLAYER_FIELD_KILLS, 0 ); SetUInt32Value( PLAYER_FIELD_LIFETIME_HONORBALE_KILLS, 0 ); @@ -584,10 +606,20 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 SetUInt32Value( PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0 ); // set starting level + uint32 start_level = getClass() != CLASS_DEATH_KNIGHT + ? sWorld.getConfig(CONFIG_START_PLAYER_LEVEL) + : sWorld.getConfig(CONFIG_START_HEROIC_PLAYER_LEVEL); + if (GetSession()->GetSecurity() >= SEC_MODERATOR) - SetUInt32Value (UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_GM_LEVEL)); - else - SetUInt32Value (UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_PLAYER_LEVEL)); + { + uint32 gm_level = sWorld.getConfig(CONFIG_START_GM_LEVEL); + if(gm_level > start_level) + start_level = gm_level; + } + + SetUInt32Value(UNIT_FIELD_LEVEL, start_level); + + InitRunes(); SetUInt32Value (PLAYER_FIELD_COINAGE, sWorld.getConfig(CONFIG_START_PLAYER_MONEY)); SetUInt32Value (PLAYER_FIELD_HONOR_CURRENCY, sWorld.getConfig(CONFIG_START_HONOR_POINTS)); @@ -651,6 +683,7 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 // base stats and related field values InitStatsForLevel(); InitTaxiNodesForLevel(); + InitGlyphsForLevel(); InitTalentForLevel(); InitPrimaryProffesions(); // to max set before any spell added @@ -663,8 +696,16 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 SetPower(POWER_MANA,GetMaxPower(POWER_MANA)); } + if(getPowerType() == POWER_RUNIC_POWER) + { + SetPower(POWER_RUNE, 8); + SetMaxPower(POWER_RUNE, 8); + SetPower(POWER_RUNIC_POWER, 0); + SetMaxPower(POWER_RUNIC_POWER, 1000); + } + // original spells - learnDefaultSpells(true); + learnDefaultSpells(); // original action bar std::list<uint16>::const_iterator action_itr[4]; @@ -706,6 +747,11 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 uint32 item_id = oEntry->ItemId[j]; + + // Hack for not existed item id in dbc 3.0.3 + if(item_id==40582) + continue; + ItemPrototype const* iProto = objmgr.GetItemPrototype(item_id); if(!iProto) { @@ -713,7 +759,9 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 continue; } - uint32 count = iProto->Stackable; // max stack by default (mostly 1) + // max stack by default (mostly 1), 1 for infinity stackable + uint32 count = iProto->Stackable > 0 ? uint32(iProto->Stackable) : 1; + if(iProto->Class==ITEM_CLASS_CONSUMABLE && iProto->SubClass==ITEM_SUBCLASS_FOOD) { switch(iProto->Spells[0].SpellCategory) @@ -872,39 +920,40 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da void Player::HandleDrowning() { - if(!m_isunderwater) + if(!(m_isunderwater&~UNDERWATER_INLAVA)) return; //if player is GM, have waterbreath, is dead or if breathing is disabled then return - if(waterbreath || isGameMaster() || !isAlive() || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING)) + if(isGameMaster() || !isAlive() || HasAuraType(SPELL_AURA_WATER_BREATHING) || GetSession()->GetSecurity() >= sWorld.getConfig(CONFIG_DISABLE_BREATHING)) { StopMirrorTimer(BREATH_TIMER); - m_isunderwater = 0; + // drop every flag _except_ LAVA - otherwise waterbreathing will prevent lava damage + m_isunderwater &= UNDERWATER_INLAVA; return; } - uint32 UnderWaterTime = 1*MINUTE*1000; // default length 1 min + uint32 UnderWaterTime = 3*MINUTE*1000; // default duration AuraList const& mModWaterBreathing = GetAurasByType(SPELL_AURA_MOD_WATER_BREATHING); for(AuraList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i) - UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifierValue()) / 100.0f); + UnderWaterTime = uint32(UnderWaterTime * (100.0f + (*i)->GetModifier()->m_amount) / 100.0f); - if ((m_isunderwater & 0x01) && !(m_isunderwater & 0x80) && isAlive()) + if ((m_isunderwater & UNDERWATER_INWATER) && !(m_isunderwater & UNDERWATER_INLAVA) && isAlive()) { //single trigger timer - if (!(m_isunderwater & 0x02)) + if (!(m_isunderwater & UNDERWATER_WATER_TRIGGER)) { - m_isunderwater|= 0x02; + m_isunderwater|= UNDERWATER_WATER_TRIGGER; m_breathTimer = UnderWaterTime + 1000; } - //single trigger "Breathbar" - if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & 0x04)) + //single trigger "show Breathbar" + if ( m_breathTimer <= UnderWaterTime && !(m_isunderwater & UNDERWATER_WATER_BREATHB)) { - m_isunderwater|= 0x04; + m_isunderwater|= UNDERWATER_WATER_BREATHB; StartMirrorTimer(BREATH_TIMER, UnderWaterTime); } //continuous trigger drowning "Damage" - if ((m_breathTimer == 0) && (m_isunderwater & 0x01)) + if ((m_breathTimer == 0) && (m_isunderwater & UNDERWATER_INWATER)) { //TODO: Check this formula uint64 guid = GetGUID(); @@ -915,74 +964,51 @@ void Player::HandleDrowning() } } //single trigger retract bar - else if (!(m_isunderwater & 0x01) && !(m_isunderwater & 0x08) && (m_isunderwater & 0x02) && (m_breathTimer > 0) && isAlive()) + else if (!(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater & UNDERWATER_WATER_TRIGGER) && (m_breathTimer > 0) && isAlive()) { - m_isunderwater = 0x08; - uint32 BreathRegen = 10; + // m_breathTimer will be reduced in ModifyMirrorTimer ModifyMirrorTimer(BREATH_TIMER, UnderWaterTime, m_breathTimer,BreathRegen); - m_isunderwater = 0x10; + m_isunderwater = UNDERWATER_WATER_BREATHB_RETRACTING; } //remove bar - else if ((m_breathTimer < 50) && !(m_isunderwater & 0x01) && (m_isunderwater == 0x10)) + else if ((m_breathTimer < 50) && !(m_isunderwater & UNDERWATER_INWATER) && (m_isunderwater == UNDERWATER_WATER_BREATHB_RETRACTING)) { StopMirrorTimer(BREATH_TIMER); - m_isunderwater = 0; + m_isunderwater = UNDERWATER_NONE; } } void Player::HandleLava() { - bool ValidArea = false; - - if ((m_isunderwater & 0x80) && isAlive()) + if ((m_isunderwater & UNDERWATER_INLAVA) && isAlive()) { - //Single trigger Set BreathTimer - if (!(m_isunderwater & 0x80)) + /* + * arrai: how is this supposed to work? UNDERWATER_INLAVA is always set in this scope! + // Single trigger Set BreathTimer + if (!(m_isunderwater & UNDERWATER_INLAVA)) { - m_isunderwater|= 0x04; + m_isunderwater|= UNDERWATER_WATER_BREATHB; m_breathTimer = 1000; } - //Reset BreathTimer and still in the lava + */ + // Reset BreathTimer and still in the lava if (!m_breathTimer) { uint64 guid = GetGUID(); uint32 damage = urand(600, 700); // TODO: Get more detailed information about lava damage - uint32 dmgZone = GetZoneId(); // TODO: Find correct "lava dealing zone" flag in Area Table - - // Deal lava damage only in lava zones. - switch(dmgZone) - { - case 0x8D: - ValidArea = false; - break; - case 0x94: - ValidArea = false; - break; - case 0x2CE: - ValidArea = false; - break; - case 0x2CF: - ValidArea = false; - break; - default: - if (dmgZone / 5 & 0x408) - ValidArea = true; - } - // if is valid area and is not gamemaster then deal damage - if ( ValidArea && !isGameMaster() ) + // if not gamemaster then deal damage + if ( !isGameMaster() ) EnvironmentalDamage(guid, DAMAGE_LAVA, damage); m_breathTimer = 1000; } - } - //Death timer disabled and WaterFlags reset - else if (m_deathState == DEAD) + else if (!isAlive()) // Disable breath timer and reset underwater flags { m_breathTimer = 0; - m_isunderwater = 0; + m_isunderwater = UNDERWATER_NONE; } } @@ -1314,6 +1340,7 @@ void Player::Update( uint32 p_time ) Pet* pet = GetPet(); if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE) && !pet->isPossessed()) + //if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID()))) { RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true); return; @@ -1363,6 +1390,7 @@ void Player::setDeathState(DeathState s) // passive spell if(!ressSpellId) ressSpellId = GetResurrectionSpellId(); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, 1); } Unit::setDeathState(s); @@ -1383,13 +1411,15 @@ void Player::setDeathState(DeathState s) void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) { - *p_data << GetGUID(); + Field *fields = result->Fetch(); + + *p_data << uint64(GetGUID()); *p_data << m_name; - *p_data << getRace(); + *p_data << uint8(getRace()); uint8 pClass = getClass(); - *p_data << pClass; - *p_data << getGender(); + *p_data << uint8(pClass); + *p_data << uint8(getGender()); uint32 bytes = GetUInt32Value(PLAYER_BYTES); *p_data << uint8(bytes); @@ -1402,16 +1432,17 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) *p_data << uint8(getLevel()); // player level // do not use GetMap! it will spawn a new instance since the bound instances are not loaded - uint32 zoneId = MapManager::Instance().GetZoneId(GetMapId(), GetPositionX(),GetPositionY()); + uint32 zoneId = MapManager::Instance().GetZoneId(GetMapId(), GetPositionX(),GetPositionY(),GetPositionZ()); sLog.outDebug("Player::BuildEnumData: m:%u, x:%f, y:%f, z:%f zone:%u", GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), zoneId); - *p_data << zoneId; - *p_data << GetMapId(); + *p_data << uint32(zoneId); + *p_data << uint32(GetMapId()); *p_data << GetPositionX(); *p_data << GetPositionY(); *p_data << GetPositionZ(); - *p_data << (result ? result->Fetch()[13].GetUInt32() : 0); + // guild id + *p_data << (result ? fields[13].GetUInt32() : 0); uint32 char_flags = 0; if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_HIDE_HELM)) @@ -1422,14 +1453,13 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) char_flags |= CHARACTER_FLAG_GHOST; if(HasAtLoginFlag(AT_LOGIN_RENAME)) char_flags |= CHARACTER_FLAG_RENAME; - // always send the flag if declined names aren't used - // to let the client select a default method of declining the name - if(!sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) || (result && result->Fetch()[14].GetCppString() != "")) + if(sWorld.getConfig(CONFIG_DECLINED_NAMES_USED) && (fields[14].GetCppString() != "")) char_flags |= CHARACTER_FLAG_DECLINED; - *p_data << (uint32)char_flags; // character flags - - *p_data << (uint8)1; // unknown + *p_data << uint32(char_flags); // character flags + // character customize (flags?) + *p_data << uint32(HasAtLoginFlag(AT_LOGIN_CUSTOMIZE) ? 1 : 0); + *p_data << uint8(1); // unknown // Pets info { @@ -1440,8 +1470,6 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) // show pet at selection character in character list only for non-ghost character if(result && isAlive() && (pClass == CLASS_WARLOCK || pClass == CLASS_HUNTER)) { - Field* fields = result->Fetch(); - uint32 entry = fields[10].GetUInt32(); CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(entry); if(cInfo) @@ -1452,36 +1480,11 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) } } - *p_data << (uint32)petDisplayId; - *p_data << (uint32)petLevel; - *p_data << (uint32)petFamily; + *p_data << uint32(petDisplayId); + *p_data << uint32(petLevel); + *p_data << uint32(petFamily); } - /*ItemPrototype const *items[EQUIPMENT_SLOT_END]; - for (int i = 0; i < EQUIPMENT_SLOT_END; i++) - items[i] = NULL; - - QueryResult *result = CharacterDatabase.PQuery("SELECT slot,item_template FROM character_inventory WHERE guid = '%u' AND bag = 0",GetGUIDLow()); - if (result) - { - do - { - Field *fields = result->Fetch(); - uint8 slot = fields[0].GetUInt8() & 255; - uint32 item_id = fields[1].GetUInt32(); - if( slot >= EQUIPMENT_SLOT_END ) - continue; - - items[slot] = objmgr.GetItemPrototype(item_id); - if(!items[slot]) - { - sLog.outError( "Player::BuildEnumData: Player %s have unknown item (id: #%u) in inventory, skipped.", GetName(),item_id ); - continue; - } - } while (result->NextRow()); - delete result; - }*/ - for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; slot++) { uint32 visualbase = PLAYER_VISIBLE_ITEM_1_0 + (slot * MAX_VISIBLE_ITEM_OFFSET); @@ -1498,20 +1501,20 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) if (proto != NULL) { - *p_data << (uint32)proto->DisplayInfoID; - *p_data << (uint8)proto->InventoryType; - *p_data << (uint32)(enchant?enchant->aura_id:0); + *p_data << uint32(proto->DisplayInfoID); + *p_data << uint8(proto->InventoryType); + *p_data << uint32(enchant ? enchant->aura_id : 0); } else { - *p_data << (uint32)0; - *p_data << (uint8)0; - *p_data << (uint32)0; // enchant? + *p_data << uint32(0); + *p_data << uint8(0); + *p_data << uint32(0); // enchant? } } - *p_data << (uint32)0; // first bag display id - *p_data << (uint8)0; // first bag inventory type - *p_data << (uint32)0; // enchant? + *p_data << uint32(0); // first bag display id + *p_data << uint8(0); // first bag inventory type + *p_data << uint32(0); // enchant? } bool Player::ToggleAFK() @@ -1596,7 +1599,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati if(GetTransport()) RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :) - SendTransferAborted(mapid, TRANSFER_ABORT_INSUF_EXPAN_LVL1); + SendTransferAborted(mapid, TRANSFER_ABORT_INSUF_EXPAN_LVL, mEntry->Expansion()); return false; // normal client can't teleport to this map... } @@ -1916,13 +1919,20 @@ void Player::RegenerateAll() { RegenerateHealth(); if (!isInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) + { Regenerate(POWER_RAGE); + if(getClass() == CLASS_DEATH_KNIGHT) + Regenerate(POWER_RUNIC_POWER); + } } Regenerate( POWER_ENERGY ); Regenerate( POWER_MANA ); + if(getClass() == CLASS_DEATH_KNIGHT) + Regenerate( POWER_RUNE ); + m_regenTimer = regenDelay; } @@ -1942,11 +1952,11 @@ void Player::Regenerate(Powers power) if (recentCast) { // Trinity Updates Mana in intervals of 2s, which is correct - addvalue = GetFloatValue(PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT) * ManaIncreaseRate * 2.00f; + addvalue = GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER) * ManaIncreaseRate * 2.00f; } else { - addvalue = GetFloatValue(PLAYER_FIELD_MOD_MANA_REGEN) * ManaIncreaseRate * 2.00f; + addvalue = GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER) * ManaIncreaseRate * 2.00f; } } break; case POWER_RAGE: // Regenerate rage @@ -1957,6 +1967,17 @@ void Player::Regenerate(Powers power) case POWER_ENERGY: // Regenerate energy (rogue) addvalue = 20; break; + case POWER_RUNIC_POWER: + { + float RunicPowerDecreaseRate = sWorld.getRate(RATE_POWER_RUNICPOWER_LOSS); + addvalue = 30 * RunicPowerDecreaseRate; // 3 RunicPower by tick + } break; + case POWER_RUNE: + { + for(uint32 i = 0; i < MAX_RUNES; ++i) + if(uint8 cd = GetRuneCooldown(i)) // if we have cooldown, reduce it... + SetRuneCooldown(i, cd - 1); // ... by 2 sec (because update is every 2 sec) + } break; case POWER_FOCUS: case POWER_HAPPINESS: break; @@ -1969,10 +1990,10 @@ void Player::Regenerate(Powers power) AuraList const& ModPowerRegenPCTAuras = GetAurasByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); for(AuraList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) if ((*i)->GetModifier()->m_miscvalue == power) - addvalue *= ((*i)->GetModifierValue() + 100) / 100.0f; + addvalue *= ((*i)->GetModifier()->m_amount + 100) / 100.0f; } - if (power != POWER_RAGE) + if (power != POWER_RAGE && power != POWER_RUNIC_POWER) { curValue += uint32(addvalue); if (curValue > maxValue) @@ -2010,7 +2031,7 @@ void Player::RegenerateHealth() { AuraList const& mModHealthRegenPct = GetAurasByType(SPELL_AURA_MOD_HEALTH_REGEN_PERCENT); for(AuraList::const_iterator i = mModHealthRegenPct.begin(); i != mModHealthRegenPct.end(); ++i) - addvalue *= (100.0f + (*i)->GetModifierValue()) / 100.0f; + addvalue *= (100.0f + (*i)->GetModifier()->m_amount) / 100.0f; } else if(HasAuraType(SPELL_AURA_MOD_REGEN_DURING_COMBAT)) addvalue *= GetTotalAuraModifier(SPELL_AURA_MOD_REGEN_DURING_COMBAT) / 100.0f; @@ -2070,21 +2091,27 @@ void Player::SetGameMaster(bool on) setFaction(35); SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); - RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); ResetContestedPvP(); getHostilRefManager().setOnlineOfflineState(false); CombatStop(); + + SetPhaseMask(PHASEMASK_ANYWHERE,false); // see and visible in all phases } else { + // restore phase + AuraList const& phases = GetAurasByType(SPELL_AURA_PHASE); + SetPhaseMask(!phases.empty() ? phases.front()->GetMiscValue() : PHASEMASK_NORMAL,false); + m_ExtraFlags &= ~ PLAYER_EXTRA_GM_ON; setFactionForRace(getRace()); RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); // restore FFA PvP Server state if(sWorld.IsFFAPvPRealm()) - SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); // restore FFA PvP area state, remove not allowed for GM mounts UpdateArea(m_areaUpdateId); @@ -2208,7 +2235,7 @@ void Player::GiveXP(uint32 xp, Unit* victim) // handle SPELL_AURA_MOD_XP_PCT auras Unit::AuraList const& ModXPPctAuras = GetAurasByType(SPELL_AURA_MOD_XP_PCT); for(Unit::AuraList::const_iterator i = ModXPPctAuras.begin();i != ModXPPctAuras.end(); ++i) - xp = uint32(xp*(1.0f + (*i)->GetModifierValue() / 100.0f)); + xp = uint32(xp*(1.0f + (*i)->GetModifier()->m_amount / 100.0f)); // XP resting bonus for kill uint32 rested_bonus_xp = victim ? GetXPRestBonus(xp) : 0; @@ -2256,13 +2283,15 @@ void Player::GiveLevel(uint32 level) data << uint32(0); data << uint32(0); data << uint32(0); + data << uint32(0); + data << uint32(0); // end for for(int i = STAT_STRENGTH; i < MAX_STATS; ++i) // Stats loop (0-4) data << uint32(int32(info.stats[i]) - GetCreateStat(Stats(i))); GetSession()->SendPacket(&data); - SetUInt32Value(PLAYER_NEXT_LEVEL_XP, Trinity::XP::xp_to_level(level)); + SetUInt32Value(PLAYER_NEXT_LEVEL_XP, objmgr.GetXPForLevel(level)); //update level, max level of skills if(getLevel()!= level) @@ -2279,6 +2308,7 @@ void Player::GiveLevel(uint32 level) InitTalentForLevel(); InitTaxiNodesForLevel(); + InitGlyphsForLevel(); UpdateAllStats(); @@ -2298,6 +2328,7 @@ void Player::GiveLevel(uint32 level) Pet* pet = GetPet(); if(pet && pet->getPetType()==SUMMON_PET) pet->GivePetLevel(level); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL); } void Player::InitTalentForLevel() @@ -2315,7 +2346,8 @@ void Player::InitTalentForLevel() } else { - uint32 talentPointsForLevel = uint32((level-9)*sWorld.getRate(RATE_TALENT)); + uint32 talentPointsForLevel = CalculateTalentsPoints(); + // if used more that have then reset if(m_usedTalentCount > talentPointsForLevel) { @@ -2342,7 +2374,7 @@ void Player::InitStatsForLevel(bool reapplyMods) objmgr.GetPlayerLevelInfo(getRace(),getClass(),getLevel(),&info); SetUInt32Value(PLAYER_FIELD_MAX_LEVEL, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ); - SetUInt32Value(PLAYER_NEXT_LEVEL_XP, Trinity::XP::xp_to_level(getLevel())); + SetUInt32Value(PLAYER_NEXT_LEVEL_XP, objmgr.GetXPForLevel(getLevel())); UpdateSkillsForLevel (); @@ -2392,11 +2424,11 @@ void Player::InitStatsForLevel(bool reapplyMods) SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, 0.0f ); SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, 0.0f ); - SetUInt32Value(UNIT_FIELD_ATTACK_POWER, 0 ); - SetUInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, 0 ); + SetInt32Value(UNIT_FIELD_ATTACK_POWER, 0 ); + SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, 0 ); SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER,0.0f); - SetUInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER, 0 ); - SetUInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MODS,0 ); + SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER, 0 ); + SetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MODS,0 ); SetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER,0.0f); // Base crit values (will be recalculated in UpdateAllStats() at loading and in _ApplyAllStatBonuses() at reset @@ -2434,6 +2466,9 @@ void Player::InitStatsForLevel(bool reapplyMods) SetFloatValue(UNIT_FIELD_POWER_COST_MODIFIER+i,0.0f); SetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,0.0f); } + // Reset no reagent cost field + for(int i = 0; i < 3; i++) + SetUInt32Value(PLAYER_NO_REAGENT_COST_1 + i, 0); // Init data for form but skip reapply item mods for form InitDataForForm(reapplyMods); @@ -2450,15 +2485,16 @@ void Player::InitStatsForLevel(bool reapplyMods) RemoveFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_PET_IN_COMBAT | UNIT_FLAG_SILENCED | UNIT_FLAG_PACIFIED | - UNIT_FLAG_DISABLE_ROTATE | UNIT_FLAG_IN_COMBAT | UNIT_FLAG_DISARMED | + UNIT_FLAG_STUNNED | UNIT_FLAG_IN_COMBAT | UNIT_FLAG_DISARMED | UNIT_FLAG_CONFUSED | UNIT_FLAG_FLEEING | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_SKINNABLE | UNIT_FLAG_MOUNT | UNIT_FLAG_TAXI_FLIGHT ); SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); // must be set // cleanup player flags (will be re-applied if need at aura load), to avoid have ghost flag without ghost aura, for example. - RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK | PLAYER_FLAGS_DND | PLAYER_FLAGS_GM | PLAYER_FLAGS_GHOST | PLAYER_FLAGS_FFA_PVP); + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK | PLAYER_FLAGS_DND | PLAYER_FLAGS_GM | PLAYER_FLAGS_GHOST | PLAYER_ALLOW_ONLY_ABILITY); - SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00); // one form stealth modified bytes + RemoveStandFlags(UNIT_STAND_FLAGS_ALL); // one form stealth modified bytes + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP | UNIT_BYTE2_FLAG_SANCTUARY); // restore if need some important flags SetUInt32Value(PLAYER_FIELD_BYTES2, 0 ); // flags empty by default @@ -2474,6 +2510,7 @@ void Player::InitStatsForLevel(bool reapplyMods) SetPower(POWER_RAGE, GetMaxPower(POWER_RAGE)); SetPower(POWER_FOCUS, 0); SetPower(POWER_HAPPINESS, 0); + SetPower(POWER_RUNIC_POWER, 0); } void Player::SendInitialSpells() @@ -2606,13 +2643,13 @@ void Player::AddNewMailDeliverTime(time_t deliver_time) } } -bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, uint16 slot_id, bool disabled) +bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool dependent, bool disabled) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); if (!spellInfo) { // do character spell book cleanup (all characters) - if(loading && !learning) // spell load case + if(!IsInWorld() && !learning) // spell load case { sLog.outError("Player::addSpell: Non-existed in SpellStore spell #%u request, deleting for all characters in `character_spell`.",spell_id); CharacterDatabase.PExecute("DELETE FROM character_spell WHERE spell = '%u'",spell_id); @@ -2626,7 +2663,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, if(!SpellMgr::IsSpellValid(spellInfo,this,false)) { // do character spell book cleanup (all characters) - if(loading && !learning) // spell load case + if(!IsInWorld() && !learning) // spell load case { sLog.outError("Player::addSpell: Broken spell #%u learning not allowed, deleting for all characters in `character_spell`.",spell_id); CharacterDatabase.PExecute("DELETE FROM character_spell WHERE spell = '%u'",spell_id); @@ -2639,29 +2676,80 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, PlayerSpellState state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED; + bool dependent_set = false; bool disabled_case = false; bool superceded_old = false; PlayerSpellMap::iterator itr = m_spells.find(spell_id); if (itr != m_spells.end()) { + uint32 next_active_spell_id = 0; + // fix activate state for non-stackable low rank (and find next spell for !active case) + if(!SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0) + { + if(uint32 next = spellmgr.GetNextSpellInChain(spell_id)) + { + if(HasSpell(next)) + { + // high rank already known so this must !active + active = false; + next_active_spell_id = next; + } + } + } + + // not do anything if already known in expected state + if(itr->second->state != PLAYERSPELL_REMOVED && itr->second->active == active && + itr->second->dependent == dependent && itr->second->disabled == disabled) + { + if(!IsInWorld() && !learning) // explicitly load from DB and then exist in it already and set correctly + itr->second->state = PLAYERSPELL_UNCHANGED; + + return false; + } + + // dependent spell known as not dependent, overwrite state + if (itr->second->state != PLAYERSPELL_REMOVED && !itr->second->dependent && dependent) + { + itr->second->dependent = dependent; + if (itr->second->state != PLAYERSPELL_NEW) + itr->second->state = PLAYERSPELL_CHANGED; + dependent_set = true; + } + // update active state for known spell if(itr->second->active != active && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled) { itr->second->active = active; - // loading && !learning == explicitly load from DB and then exist in it already and set correctly - if(loading && !learning) + if(!IsInWorld() && !learning && !dependent_set) // explicitly load from DB and then exist in it already and set correctly itr->second->state = PLAYERSPELL_UNCHANGED; else if(itr->second->state != PLAYERSPELL_NEW) itr->second->state = PLAYERSPELL_CHANGED; - if(!active) + if(active) { - WorldPacket data(SMSG_REMOVED_SPELL, 4); - data << uint16(spell_id); - GetSession()->SendPacket(&data); + if (IsPassiveSpell(spell_id) && IsNeedCastPassiveSpellAtLearn(spellInfo)) + CastSpell (this,spell_id,true); } + else if(IsInWorld()) + { + if(next_active_spell_id) + { + // update spell ranks in spellbook and action bar + WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); + data << uint16(spell_id); + data << uint16(next_active_spell_id); + GetSession()->SendPacket( &data ); + } + else + { + WorldPacket data(SMSG_REMOVED_SPELL, 4); + data << uint16(spell_id); + GetSession()->SendPacket(&data); + } + } + return active; // learn (show in spell book if active now) } @@ -2690,7 +2778,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, default: // known not saved yet spell (new or modified) { // can be in case spell loading but learned at some previous spell loading - if(loading && !learning) + if(!IsInWorld() && !learning && !dependent_set) itr->second->state = PLAYERSPELL_UNCHANGED; return false; @@ -2712,10 +2800,6 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, if(!rankSpellId || rankSpellId==spell_id) continue; - // skip unknown ranks - if(!HasSpell(rankSpellId)) - continue; - removeSpell(rankSpellId); } } @@ -2723,16 +2807,17 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, // non talent spell: learn low ranks (recursive call) else if(uint32 prev_spell = spellmgr.GetPrevSpellInChain(spell_id)) { - if(loading) // at spells loading, no output, but allow save - addSpell(prev_spell,active,true,loading,SPELL_WITHOUT_SLOT_ID,disabled); + if(!IsInWorld() || disabled) // at spells loading, no output, but allow save + addSpell(prev_spell,active,true,true,disabled); else // at normal learning - learnSpell(prev_spell); + learnSpell(prev_spell,true); } PlayerSpell *newspell = new PlayerSpell; - newspell->active = active; - newspell->state = state; - newspell->disabled = disabled; + newspell->state = state; + newspell->active = active; + newspell->dependent = dependent; + newspell->disabled = disabled; // replace spells in action bars and spellbook to bigger rank if only one spell rank must be accessible if(newspell->active && !newspell->disabled && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0) @@ -2749,7 +2834,7 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, { if(spellmgr.IsHighRankOfSpell(spell_id,itr->first)) { - if(!loading) // not send spell (re-/over-)learn packets at loading + if(IsInWorld()) // not send spell (re-/over-)learn packets at loading { WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); data << uint16(itr->first); @@ -2759,12 +2844,13 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, // mark old spell as disable (SMSG_SUPERCEDED_SPELL replace it in client by new) itr->second->active = false; - itr->second->state = PLAYERSPELL_CHANGED; + if(itr->second->state != PLAYERSPELL_NEW) + itr->second->state = PLAYERSPELL_CHANGED; superceded_old = true; // new spell replace old in action bars and spell book. } else if(spellmgr.IsHighRankOfSpell(itr->first,spell_id)) { - if(!loading) // not send spell (re-/over-)learn packets at loading + if(IsInWorld()) // not send spell (re-/over-)learn packets at loading { WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); data << uint16(spell_id); @@ -2782,23 +2868,6 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, } } - uint16 tmpslot=slot_id; - - if (tmpslot == SPELL_WITHOUT_SLOT_ID) - { - uint16 maxid = 0; - PlayerSpellMap::iterator itr; - for (itr = m_spells.begin(); itr != m_spells.end(); ++itr) - { - if(itr->second->state == PLAYERSPELL_REMOVED) - continue; - if (itr->second->slotId > maxid) - maxid = itr->second->slotId; - } - tmpslot = maxid + 1; - } - - newspell->slotId = tmpslot; m_spells[spell_id] = newspell; // return false if spell disabled @@ -2818,23 +2887,8 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, // also cast passive spells (including all talents without SPELL_EFFECT_LEARN_SPELL) with additional checks else if (IsPassiveSpell(spell_id)) { - // if spell doesn't require a stance or the player is in the required stance - if( ( !spellInfo->Stances && - spell_id != 5420 && spell_id != 5419 && spell_id != 7376 && - spell_id != 7381 && spell_id != 21156 && spell_id != 21009 && - spell_id != 21178 && spell_id != 33948 && spell_id != 40121 ) || - m_form != 0 && (spellInfo->Stances & (1<<(m_form-1))) || - (spell_id == 5420 && m_form == FORM_TREE) || - (spell_id == 5419 && m_form == FORM_TRAVEL) || - (spell_id == 7376 && m_form == FORM_DEFENSIVESTANCE) || - (spell_id == 7381 && m_form == FORM_BERSERKERSTANCE) || - (spell_id == 21156 && m_form == FORM_BATTLESTANCE)|| - (spell_id == 21178 && (m_form == FORM_BEAR || m_form == FORM_DIREBEAR) ) || - (spell_id == 33948 && m_form == FORM_FLIGHT) || - (spell_id == 40121 && m_form == FORM_FLIGHT_EPIC) ) - //Check CasterAuraStates - if (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState))) - CastSpell(this, spell_id, true); + if(IsNeedCastPassiveSpellAtLearn(spellInfo)) + CastSpell(this, spell_id, true); } else if( IsSpellHaveEffect(spellInfo,SPELL_EFFECT_SKILL_STEP) ) { @@ -2888,8 +2942,6 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, continue; if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL || - // poison special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL - pSkill->id==SKILL_POISONS && _spell_idx->second->max_value==0 || // lockpicking special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL pSkill->id==SKILL_LOCKPICKING && _spell_idx->second->max_value==0 ) { @@ -2919,37 +2971,71 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, { if(!itr->second.autoLearned) { - if(loading) // at spells loading, no output, but allow save - addSpell(itr->second.spell,true,true,loading); + if(!IsInWorld() || !itr->second.active) // at spells loading, no output, but allow save + addSpell(itr->second.spell,itr->second.active,true,true,false); else // at normal learning - learnSpell(itr->second.spell); + learnSpell(itr->second.spell,true); } } + if(IsInWorld()) + { + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS); + } + // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell return active && !disabled && !superceded_old; } -void Player::learnSpell(uint32 spell_id) +bool Player::IsNeedCastPassiveSpellAtLearn(SpellEntry const* spellInfo) const +{ + bool need_cast = false; + + switch(spellInfo->Id) + { + // some spells not have stance data expacted cast at form change or present + case 5420: need_cast = (m_form == FORM_TREE); break; + case 5419: need_cast = (m_form == FORM_TRAVEL); break; + case 7376: need_cast = (m_form == FORM_DEFENSIVESTANCE); break; + case 7381: need_cast = (m_form == FORM_BERSERKERSTANCE); break; + case 21156: need_cast = (m_form == FORM_BATTLESTANCE); break; + case 21178: need_cast = (m_form == FORM_BEAR || m_form == FORM_DIREBEAR); break; + case 33948: need_cast = (m_form == FORM_FLIGHT); break; + case 34764: need_cast = (m_form == FORM_FLIGHT); break; + case 40121: need_cast = (m_form == FORM_FLIGHT_EPIC); break; + case 40122: need_cast = (m_form == FORM_FLIGHT_EPIC); break; + // another spells have proper stance data + default: need_cast = !spellInfo->Stances || m_form != 0 && (spellInfo->Stances & (1<<(m_form-1))); break; + } + + //Check CasterAuraStates + return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraState(spellInfo->CasterAuraState))); +} + +void Player::learnSpell(uint32 spell_id, bool dependent) { PlayerSpellMap::iterator itr = m_spells.find(spell_id); bool disabled = (itr != m_spells.end()) ? itr->second->disabled : false; bool active = disabled ? itr->second->active : true; - bool learning = addSpell(spell_id,active); + bool learning = addSpell(spell_id,active,true,dependent,false); // learn all disabled higher ranks (recursive) - SpellChainNode const* node = spellmgr.GetSpellChainNode(spell_id); - if (node) + if(disabled) { - PlayerSpellMap::iterator iter = m_spells.find(node->next); - if (disabled && iter != m_spells.end() && iter->second->disabled ) - learnSpell(node->next); + SpellChainNode const* node = spellmgr.GetSpellChainNode(spell_id); + if(node) + { + PlayerSpellMap::iterator iter = m_spells.find(node->next); + if (iter != m_spells.end() && iter->second->disabled ) + learnSpell(node->next,false); + } } - // prevent duplicated entires in spell book - if(!learning) + // prevent duplicated entires in spell book, also not send if not in world (loading) + if(!learning || !IsInWorld ()) return; WorldPacket data(SMSG_LEARNED_SPELL, 4); @@ -2957,7 +3043,7 @@ void Player::learnSpell(uint32 spell_id) GetSession()->SendPacket(&data); } -void Player::removeSpell(uint32 spell_id, bool disabled) +void Player::removeSpell(uint32 spell_id, bool disabled, bool update_action_bar_for_low_rank) { PlayerSpellMap::iterator itr = m_spells.find(spell_id); if (itr == m_spells.end()) @@ -2979,10 +3065,8 @@ void Player::removeSpell(uint32 spell_id, bool disabled) for (uint32 i=reqMap.count(spell_id);i>0;i--,itr2++) removeSpell(itr2->second,disabled); - // removing - WorldPacket data(SMSG_REMOVED_SPELL, 4); - data << uint16(spell_id); - GetSession()->SendPacket(&data); + bool cur_active = itr->second->active; + bool cur_dependent = itr->second->dependent; if (disabled) { @@ -3075,8 +3159,6 @@ void Player::removeSpell(uint32 spell_id, bool disabled) continue; if(_spell_idx->second->learnOnGetSkill == ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL || - // poison special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL - pSkill->id==SKILL_POISONS && _spell_idx->second->max_value==0 || // lockpicking special case, not have ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL pSkill->id==SKILL_LOCKPICKING && _spell_idx->second->max_value==0 ) { @@ -3096,6 +3178,58 @@ void Player::removeSpell(uint32 spell_id, bool disabled) for(SpellLearnSpellMap::const_iterator itr2 = spell_begin; itr2 != spell_end; ++itr2) removeSpell(itr2->second.spell, disabled); + + // activate lesser rank in spellbook/action bar, and cast it if need + bool prev_activate = false; + + if(uint32 prev_id = spellmgr.GetPrevSpellInChain (spell_id)) + { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spell_id); + + // if talent then lesser rank also talent and need learn + if(talentCosts) + learnSpell (prev_id,false); + // if ranked non-stackable spell: need activate lesser rank and update dendence state + else if(cur_active && !SpellMgr::canStackSpellRanks(spellInfo) && spellmgr.GetSpellRank(spellInfo->Id) != 0) + { + // need manually update dependence state (learn spell ignore like attempts) + PlayerSpellMap::iterator prev_itr = m_spells.find(prev_id); + if (prev_itr != m_spells.end()) + { + if(prev_itr->second->dependent != cur_dependent) + { + prev_itr->second->dependent = cur_dependent; + if(prev_itr->second->state != PLAYERSPELL_NEW) + prev_itr->second->state = PLAYERSPELL_CHANGED; + } + + // now re-learn if need re-activate + if(cur_active && !prev_itr->second->active) + { + if(addSpell(prev_id,true,false,prev_itr->second->dependent,prev_itr->second->disabled)) + { + if(update_action_bar_for_low_rank) + { + // downgrade spell ranks in spellbook and action bar + WorldPacket data(SMSG_SUPERCEDED_SPELL, (4)); + data << uint16(spell_id); + data << uint16(prev_id); + GetSession()->SendPacket( &data ); + prev_activate = true; + } + } + } + } + } + } + + // remove from spell book if not replaced by lesser rank + if(!prev_activate) + { + WorldPacket data(SMSG_REMOVED_SPELL, 4); + data << uint16(spell_id); + GetSession()->SendPacket(&data); + } } void Player::RemoveArenaSpellCooldowns() @@ -3238,8 +3372,7 @@ bool Player::resetTalents(bool no_cost) CharacterDatabase.PExecute("UPDATE characters set at_login = at_login & ~ %u WHERE guid ='%u'", uint32(AT_LOGIN_RESET_TALENTS), GetGUIDLow()); } - uint32 level = getLevel(); - uint32 talentPointsForLevel = level < 10 ? 0 : uint32((level-9)*sWorld.getRate(RATE_TALENT)); + uint32 talentPointsForLevel = CalculateTalentsPoints(); if (m_usedTalentCount == 0) { @@ -3319,18 +3452,6 @@ bool Player::resetTalents(bool no_cost) return true; } -bool Player::_removeSpell(uint16 spell_id) -{ - PlayerSpellMap::iterator itr = m_spells.find(spell_id); - if (itr != m_spells.end()) - { - delete itr->second; - m_spells.erase(itr); - return true; - } - return false; -} - Mail* Player::GetMail(uint32 id) { for(PlayerMails::iterator itr = m_mail.begin(); itr != m_mail.end(); ++itr) @@ -3376,50 +3497,46 @@ void Player::InitVisibleBits() { updateVisualBits.SetCount(PLAYER_END); - // TODO: really implement OWNER_ONLY and GROUP_ONLY. Flags can be found in UpdateFields.h - updateVisualBits.SetBit(OBJECT_FIELD_GUID); updateVisualBits.SetBit(OBJECT_FIELD_TYPE); + updateVisualBits.SetBit(OBJECT_FIELD_ENTRY); updateVisualBits.SetBit(OBJECT_FIELD_SCALE_X); - - updateVisualBits.SetBit(UNIT_FIELD_CHARM); - updateVisualBits.SetBit(UNIT_FIELD_CHARM+1); - - updateVisualBits.SetBit(UNIT_FIELD_SUMMON); - updateVisualBits.SetBit(UNIT_FIELD_SUMMON+1); - - updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY); - updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY+1); - - updateVisualBits.SetBit(UNIT_FIELD_TARGET); - updateVisualBits.SetBit(UNIT_FIELD_TARGET+1); - - updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT); - updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT+1); - + updateVisualBits.SetBit(UNIT_FIELD_CHARM + 0); + updateVisualBits.SetBit(UNIT_FIELD_CHARM + 1); + updateVisualBits.SetBit(UNIT_FIELD_SUMMON + 0); + updateVisualBits.SetBit(UNIT_FIELD_SUMMON + 1); + updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY + 0); + updateVisualBits.SetBit(UNIT_FIELD_CHARMEDBY + 1); + updateVisualBits.SetBit(UNIT_FIELD_TARGET + 0); + updateVisualBits.SetBit(UNIT_FIELD_TARGET + 1); + updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT + 0); + updateVisualBits.SetBit(UNIT_FIELD_CHANNEL_OBJECT + 1); + updateVisualBits.SetBit(UNIT_FIELD_BYTES_0); updateVisualBits.SetBit(UNIT_FIELD_HEALTH); updateVisualBits.SetBit(UNIT_FIELD_POWER1); updateVisualBits.SetBit(UNIT_FIELD_POWER2); updateVisualBits.SetBit(UNIT_FIELD_POWER3); updateVisualBits.SetBit(UNIT_FIELD_POWER4); updateVisualBits.SetBit(UNIT_FIELD_POWER5); - + updateVisualBits.SetBit(UNIT_FIELD_POWER6); + updateVisualBits.SetBit(UNIT_FIELD_POWER7); updateVisualBits.SetBit(UNIT_FIELD_MAXHEALTH); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER1); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER2); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER3); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER4); updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER5); - + updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER6); + updateVisualBits.SetBit(UNIT_FIELD_MAXPOWER7); updateVisualBits.SetBit(UNIT_FIELD_LEVEL); updateVisualBits.SetBit(UNIT_FIELD_FACTIONTEMPLATE); - updateVisualBits.SetBit(UNIT_FIELD_BYTES_0); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_ID + 0); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_ID + 1); + updateVisualBits.SetBit(UNIT_VIRTUAL_ITEM_SLOT_ID + 2); updateVisualBits.SetBit(UNIT_FIELD_FLAGS); updateVisualBits.SetBit(UNIT_FIELD_FLAGS_2); - for(uint16 i = UNIT_FIELD_AURA; i < UNIT_FIELD_AURASTATE; ++i) - updateVisualBits.SetBit(i); updateVisualBits.SetBit(UNIT_FIELD_AURASTATE); - updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME); + updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME + 0); updateVisualBits.SetBit(UNIT_FIELD_BASEATTACKTIME + 1); updateVisualBits.SetBit(UNIT_FIELD_BOUNDINGRADIUS); updateVisualBits.SetBit(UNIT_FIELD_COMBATREACH); @@ -3432,10 +3549,12 @@ void Player::InitVisibleBits() updateVisualBits.SetBit(UNIT_DYNAMIC_FLAGS); updateVisualBits.SetBit(UNIT_CHANNEL_SPELL); updateVisualBits.SetBit(UNIT_MOD_CAST_SPEED); + updateVisualBits.SetBit(UNIT_FIELD_BASE_MANA); updateVisualBits.SetBit(UNIT_FIELD_BYTES_2); + updateVisualBits.SetBit(UNIT_FIELD_HOVERHEIGHT); - updateVisualBits.SetBit(PLAYER_DUEL_ARBITER); - updateVisualBits.SetBit(PLAYER_DUEL_ARBITER+1); + updateVisualBits.SetBit(PLAYER_DUEL_ARBITER + 0); + updateVisualBits.SetBit(PLAYER_DUEL_ARBITER + 1); updateVisualBits.SetBit(PLAYER_FLAGS); updateVisualBits.SetBit(PLAYER_GUILDID); updateVisualBits.SetBit(PLAYER_GUILDRANK); @@ -3446,29 +3565,29 @@ void Player::InitVisibleBits() updateVisualBits.SetBit(PLAYER_GUILD_TIMESTAMP); // PLAYER_QUEST_LOG_x also visible bit on official (but only on party/raid)... - for(uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i+=4) + for(uint16 i = PLAYER_QUEST_LOG_1_1; i < PLAYER_QUEST_LOG_25_2; i += 4) updateVisualBits.SetBit(i); - //Players visible items are not inventory stuff - //431) = 884 (0x374) = main weapon - for(uint16 i = 0; i < EQUIPMENT_SLOT_END; i++) + // Players visible items are not inventory stuff + for(uint16 i = 0; i < EQUIPMENT_SLOT_END; ++i) { - // item creator - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + (i*MAX_VISIBLE_ITEM_OFFSET) + 0); - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + (i*MAX_VISIBLE_ITEM_OFFSET) + 1); + uint32 offset = i * MAX_VISIBLE_ITEM_OFFSET; - uint16 visual_base = PLAYER_VISIBLE_ITEM_1_0 + (i*MAX_VISIBLE_ITEM_OFFSET); + // item creator + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + 0 + offset); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_CREATOR + 1 + offset); // item entry - updateVisualBits.SetBit(visual_base + 0); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_0 + 0 + offset); - // item enchantment IDs - for(uint8 j = 0; j < MAX_INSPECTED_ENCHANTMENT_SLOT; ++j) - updateVisualBits.SetBit(visual_base + 1 + j); + // item enchantments + for(uint8 j = 0; j < MAX_ENCHANTMENT_SLOT; ++j) + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_0 + 1 + j + offset); // random properties - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 0 + (i*MAX_VISIBLE_ITEM_OFFSET)); - updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + 1 + (i*MAX_VISIBLE_ITEM_OFFSET)); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PROPERTIES + offset); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_SEED + offset); + updateVisualBits.SetBit(PLAYER_VISIBLE_ITEM_1_PAD + offset); } updateVisualBits.SetBit(PLAYER_CHOSEN_TITLE); @@ -3486,7 +3605,6 @@ void Player::BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) if(target == this) { - for(int i = INVENTORY_SLOT_BAG_START; i < BANK_SLOT_BAG_END; i++) { if(m_items[i] == NULL) @@ -3494,7 +3612,7 @@ void Player::BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) m_items[i]->BuildCreateUpdateBlockForPlayer( data, target ); } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { if(m_items[i] == NULL) continue; @@ -3527,7 +3645,7 @@ void Player::DestroyForPlayer( Player *target ) const m_items[i]->DestroyForPlayer( target ); } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { if(m_items[i] == NULL) continue; @@ -3539,8 +3657,16 @@ void Player::DestroyForPlayer( Player *target ) const bool Player::HasSpell(uint32 spell) const { - PlayerSpellMap::const_iterator itr = m_spells.find((uint16)spell); - return (itr != m_spells.end() && itr->second->state != PLAYERSPELL_REMOVED && !itr->second->disabled); + PlayerSpellMap::const_iterator itr = m_spells.find(spell); + return (itr != m_spells.end() && itr->second->state != PLAYERSPELL_REMOVED && + !itr->second->disabled); +} + +bool Player::HasActiveSpell(uint32 spell) const +{ + PlayerSpellMap::const_iterator itr = m_spells.find(spell); + return (itr != m_spells.end() && itr->second->state != PLAYERSPELL_REMOVED && + itr->second->active && !itr->second->disabled); } TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell) const @@ -3548,22 +3674,22 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell if (!trainer_spell) return TRAINER_SPELL_RED; - if (!trainer_spell->spell) + if (!trainer_spell->learnedSpell) return TRAINER_SPELL_RED; // known spell - if(HasSpell(trainer_spell->spell)) + if(HasSpell(trainer_spell->learnedSpell)) return TRAINER_SPELL_GRAY; // check race/class requirement - if(!IsSpellFitByClassAndRace(trainer_spell->spell)) + if(!IsSpellFitByClassAndRace(trainer_spell->learnedSpell)) return TRAINER_SPELL_RED; // check level requirement - if(getLevel() < trainer_spell->reqlevel) + if(getLevel() < trainer_spell->reqLevel) return TRAINER_SPELL_RED; - if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->spell)) + if(SpellChainNode const* spell_chain = spellmgr.GetSpellChainNode(trainer_spell->learnedSpell)) { // check prev.rank requirement if(spell_chain->prev && !HasSpell(spell_chain->prev)) @@ -3578,11 +3704,11 @@ TrainerSpellState Player::GetTrainerSpellState(TrainerSpell const* trainer_spell } // check skill requirement - if(trainer_spell->reqskill && GetBaseSkillValue(trainer_spell->reqskill) < trainer_spell->reqskillvalue) + if(trainer_spell->reqSkill && GetBaseSkillValue(trainer_spell->reqSkill) < trainer_spell->reqSkillValue) return TRAINER_SPELL_RED; // exist, already checked at loading - SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->spell); + SpellEntry const* spell = sSpellStore.LookupEntry(trainer_spell->learnedSpell); // secondary prof. or not prof. spell uint32 skill = spell->EffectMiscValue[1]; @@ -3615,27 +3741,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC } // remove from arena teams - uint32 at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_2v2); - if(at_id != 0) - { - ArenaTeam * at = objmgr.GetArenaTeamById(at_id); - if(at) - at->DelMember(playerguid); - } - at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_3v3); - if(at_id != 0) - { - ArenaTeam * at = objmgr.GetArenaTeamById(at_id); - if(at) - at->DelMember(playerguid); - } - at_id = GetArenaTeamIdFromDB(playerguid,ARENA_TEAM_5v5); - if(at_id != 0) - { - ArenaTeam * at = objmgr.GetArenaTeamById(at_id); - if(at) - at->DelMember(playerguid); - } + LeaveAllArenaTeams(playerguid); // the player was uninvited already on logout so just remove from group QueryResult *resultGroup = CharacterDatabase.PQuery("SELECT leaderGuid FROM group_member WHERE memberGuid='%u'", guid); @@ -3676,15 +3782,16 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC MailItemsInfo mi; if(has_items) { - QueryResult *resultItems = CharacterDatabase.PQuery("SELECT item_guid,item_template FROM mail_items WHERE mail_id='%u'", mail_id); + // data needs to be at first place for Item::LoadFromDB + QueryResult *resultItems = CharacterDatabase.PQuery("SELECT data,item_guid,item_template FROM mail_items JOIN item_instance ON item_guid = guid WHERE mail_id='%u'", mail_id); if(resultItems) { do { Field *fields2 = resultItems->Fetch(); - uint32 item_guidlow = fields2[0].GetUInt32(); - uint32 item_template = fields2[1].GetUInt32(); + uint32 item_guidlow = fields2[1].GetUInt32(); + uint32 item_template = fields2[2].GetUInt32(); ItemPrototype const* itemProto = objmgr.GetItemPrototype(item_template); if(!itemProto) @@ -3694,7 +3801,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC } Item *pItem = NewItemOrBag(itemProto); - if(!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER))) + if(!pItem->LoadFromDB(item_guidlow, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER),resultItems)) { pItem->FSetState(ITEM_REMOVED); pItem->SaveToDB(); // it also deletes item object ! @@ -3757,6 +3864,8 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC CharacterDatabase.PExecute("DELETE FROM mail_items WHERE receiver = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_pet WHERE owner = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_pet_declinedname WHERE owner = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = '%u'",guid); + CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = '%u'",guid); CharacterDatabase.CommitTransaction(); //LoginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID); @@ -3787,6 +3896,10 @@ void Player::SetMovement(PlayerMovementType pType) */ void Player::BuildPlayerRepop() { + WorldPacket data(SMSG_PRE_RESURRECT, GetPackGUID().size()); + data.append(GetPackGUID()); + GetSession()->SendPacket(&data); + if(getRace() == RACE_NIGHTELF) CastSpell(this, 20584, true); // auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) CastSpell(this, 8326, true); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) @@ -3831,7 +3944,8 @@ void Player::BuildPlayerRepop() SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, (float)1.0); //see radius of death player? - SetByteValue(UNIT_FIELD_BYTES_1, 3, PLAYER_STATE_FLAG_ALWAYS_STAND); + // set and clear other + SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND); } void Player::SendDelayResponse(const uint32 ml_seconds) @@ -3906,8 +4020,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness) { if(Aura* Aur = GetAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,i)) { - Aur->SetAuraDuration(delta*1000); - Aur->UpdateAuraDuration(); + Aur->SetAuraDurationAndUpdate(delta*1000); } } } @@ -3948,8 +4061,7 @@ void Player::CreateCorpse() Corpse *corpse = new Corpse( (m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH) ? CORPSE_RESURRECTABLE_PVP : CORPSE_RESURRECTABLE_PVE ); SetPvPDeath(false); - if(!corpse->Create(objmgr.GenerateLowGuid(HIGHGUID_CORPSE), this, GetMapId(), GetPositionX(), - GetPositionY(), GetPositionZ(), GetOrientation())) + if(!corpse->Create(objmgr.GenerateLowGuid(HIGHGUID_CORPSE), this)) { delete corpse; return; @@ -4445,7 +4557,7 @@ uint32 Player::GetShieldBlockValue() const { BaseModGroup modGroup = SHIELD_BLOCK_VALUE; - float value = GetTotalBaseModValue(modGroup) + GetStat(STAT_STRENGTH)/20 - 1; + float value = GetTotalBaseModValue(modGroup) + GetStat(STAT_STRENGTH) * 0.5f - 10; value = (value < 0) ? 0 : value; @@ -4634,7 +4746,18 @@ float Player::OCTRegenMPPerSpirit() void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply) { - ApplyModUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, value, apply); + m_baseRatingValue[cr]+=(apply ? value : -value); + + int32 amount = uint32(m_baseRatingValue[cr]); + // Apply bonus from SPELL_AURA_MOD_RATING_FROM_STAT + // stat used stored in miscValueB for this aura + AuraList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT); + for(AuraList::const_iterator i = modRatingFromStat.begin();i != modRatingFromStat.end(); ++i) + if ((*i)->GetMiscValue() & (1<<cr)) + amount += int32(GetStat(Stats((*i)->GetMiscBValue())) * (*i)->GetModifier()->m_amount / 100.0f); + if (amount < 0) + amount = 0; + SetUInt32Value(PLAYER_FIELD_COMBAT_RATING_1 + cr, uint32(amount)); float RatingCoeffecient = GetRatingCoefficient(cr); float RatingChange = 0.0f; @@ -4657,16 +4780,13 @@ void Player::ApplyRatingMod(CombatRating cr, int32 value, bool apply) UpdateBlockPercentage(); break; case CR_HIT_MELEE: - RatingChange = value / RatingCoeffecient; - m_modMeleeHitChance += apply ? RatingChange : -RatingChange; + UpdateMeleeHitChances(); break; case CR_HIT_RANGED: - RatingChange = value / RatingCoeffecient; - m_modRangedHitChance += apply ? RatingChange : -RatingChange; + UpdateRangedHitChances(); break; case CR_HIT_SPELL: - RatingChange = value / RatingCoeffecient; - m_modSpellHitChance += apply ? RatingChange : -RatingChange; + UpdateSpellHitChances(); break; case CR_CRIT_MELEE: if(affectStats) @@ -4764,6 +4884,7 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step) new_value = max; SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,max)); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL); return true; } @@ -4799,7 +4920,7 @@ bool Player::UpdateCraftSkill(uint32 spellid) if(spellEntry && spellEntry->Mechanic==MECHANIC_DISCOVERY) { if(uint32 discoveredSpell = GetSkillDiscoverySpell(_spell_idx->second->skillId, spellid, this)) - learnSpell(discoveredSpell); + learnSpell(discoveredSpell,false); } uint32 craft_skill_gain = sWorld.getConfig(CONFIG_SKILL_GAIN_CRAFTING); @@ -4826,6 +4947,7 @@ bool Player::UpdateGatherSkill(uint32 SkillId, uint32 SkillValue, uint32 RedLeve case SKILL_HERBALISM: case SKILL_LOCKPICKING: case SKILL_JEWELCRAFTING: + case SKILL_INSCRIPTION: return UpdateSkillPro(SkillId, SkillGainChance(SkillValue, RedLevel+100, RedLevel+50, RedLevel+25)*Multiplicator,gathering_skill_gain); case SKILL_SKINNING: if( sWorld.getConfig(CONFIG_SKILL_CHANCE_SKINNING_STEPS)==0) @@ -4854,6 +4976,11 @@ bool Player::UpdateFishingSkill() return UpdateSkillPro(SKILL_FISHING,chance*10,gathering_skill_gain); } +// levels sync. with spell requirement for skill levels to learn +// bonus abilities in sSkillLineAbilityStore +// Used only to avoid scan DBC at each skill grow +static uint32 bonusSkillLevels[] = {75,150,225,300,375,450}; + bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) { sLog.outDebug("UpdateSkillPro(SkillId %d, Chance %3.1f%%)", SkillId, Chance/10.0); @@ -4888,6 +5015,15 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) new_value = MaxValue; SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,MaxValue)); + for(uint32* bsl = &bonusSkillLevels[0]; *bsl; ++bsl) + { + if((SkillValue < *bsl && new_value >= *bsl)) + { + learnSkillRewardedSpells( SkillId, new_value); + break; + } + } + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL); sLog.outDebug("Player::UpdateSkillPro Chance=%3.1f%% taken", Chance/10.0); return true; } @@ -4935,22 +5071,8 @@ void Player::UpdateWeaponSkill (WeaponAttackType attType) UpdateAllCritPercentages(); } -void Player::UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, MeleeHitOutcome outcome, bool defence) +void Player::UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, bool defence) { -/* Not need, this checked on call this func from trigger system - switch(outcome) - { - case MELEE_HIT_CRIT: - case MELEE_HIT_DODGE: - case MELEE_HIT_PARRY: - case MELEE_HIT_BLOCK: - case MELEE_HIT_BLOCK_CRIT: - return; - - default: - break; - } -*/ uint32 plevel = getLevel(); // if defense than pVictim == attacker uint32 greylevel = Trinity::XP::GetGrayLevel(plevel); uint32 moblevel = pVictim->getLevelForTarget(this); @@ -5047,7 +5169,7 @@ void Player::UpdateSkillsToMaxSkillsForLevel() if (GetUInt32Value(PLAYER_SKILL_INDEX(i))) { uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; - if( IsProfessionSkill(pskill) || pskill == SKILL_RIDING ) + if( IsProfessionOrRidingSkill(pskill)) continue; uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)); @@ -5075,7 +5197,11 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) if(i<PLAYER_MAX_SKILLS) //has skill { if(currVal) + { SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(currVal,maxVal)); + learnSkillRewardedSpells(id, currVal); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL); + } else //remove { // clear skill fields @@ -5083,27 +5209,11 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),0); SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0); - // remove spells that depend on this skill when removing the skill - for (PlayerSpellMap::const_iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next) - { - ++next; - if(itr->second->state == PLAYERSPELL_REMOVED) - continue; - - SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(itr->first); - SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(itr->first); - - for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) - { - if (_spell_idx->second->skillId == id) - { - // this may remove more than one spell (dependents) - removeSpell(itr->first); - next = m_spells.begin(); - break; - } - } - } + // remove all spells that related to this skill + for (uint32 j=0; j<sSkillLineAbilityStore.GetNumRows(); ++j) + if(SkillLineAbilityEntry const *pAbility = sSkillLineAbilityStore.LookupEntry(j)) + if (pAbility->skillId==id) + removeSpell(spellmgr.GetFirstSpellInChain(pAbility->spellId)); } } else if(currVal) //add @@ -5123,6 +5233,7 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) else SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0)); SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(currVal,maxVal)); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL); // apply skill bonuses SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0); @@ -5140,7 +5251,7 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) (*i)->ApplyModifier(true); // Learn all spells for skill - learnSkillRewardedSpells(id); + learnSkillRewardedSpells(id, currVal); return; } } @@ -5238,6 +5349,22 @@ uint16 Player::GetPureSkillValue(uint32 skill) const return 0; } +int16 Player::GetSkillPermBonusValue(uint32 skill) const +{ + if(!skill) + return 0; + + for (int i = 0; i < PLAYER_MAX_SKILLS; i++) + { + if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill) + { + return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i))); + } + } + + return 0; +} + int16 Player::GetSkillTempBonusValue(uint32 skill) const { if(!skill) @@ -5419,14 +5546,14 @@ void Player::CheckExploreSystem() if (isInFlight()) return; - uint16 areaFlag=MapManager::Instance().GetBaseMap(GetMapId())->GetAreaFlag(GetPositionX(),GetPositionY()); + uint16 areaFlag=MapManager::Instance().GetBaseMap(GetMapId())->GetAreaFlag(GetPositionX(),GetPositionY(),GetPositionZ()); if(areaFlag==0xffff) return; int offset = areaFlag / 32; if(offset >= 128) { - sLog.outError("ERROR: Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < 64 ).",areaFlag,GetPositionX(),GetPositionY(),offset,offset); + sLog.outError("ERROR: Wrong area flag %u in map data for (X: %f Y: %f) point to field PLAYER_EXPLORED_ZONES_1 + %u ( %u must be < 128 ).",areaFlag,GetPositionX(),GetPositionY(),offset,offset); return; } @@ -5437,6 +5564,8 @@ void Player::CheckExploreSystem() { SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields | val)); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA); + AreaTableEntry const *p = GetAreaEntryByAreaFlagAndMap(areaFlag,GetMapId()); if(!p) { @@ -5533,6 +5662,7 @@ void Player::SendFactionState(FactionState const* faction) const { WorldPacket data(SMSG_SET_FACTION_STANDING, (16)); // last check 2.4.0 data << (float) 0; // unk 2.4.0 + data << (uint8) 0; // wotlk 8634 data << (uint32) 1; // count // for data << (uint32) faction->ReputationListID; @@ -5864,7 +5994,8 @@ bool Player::ModifyOneFactionReputation(FactionEntry const* factionEntry, int32 } } } - + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION); SendFactionState(&(itr->second)); return true; @@ -5930,6 +6061,8 @@ bool Player::SetOneFactionReputation(FactionEntry const* factionEntry, int32 sta SetFactionAtWar(&itr->second,true); SendFactionState(&(itr->second)); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION); return true; } return false; @@ -6128,12 +6261,7 @@ bool Player::RewardHonor(Unit *uVictim, uint32 groupsize, float honor, bool pvpt victim_guid = 0; // Don't show HK: <rank> message, only log. } - if(k_level <= 5) - k_grey = 0; - else if( k_level <= 39 ) - k_grey = k_level - 5 - k_level/10; - else - k_grey = k_level - 1 - k_level/5; + k_grey = Trinity::XP::GetGrayLevel(k_level); if(v_level<=k_grey) return false; @@ -6169,6 +6297,8 @@ bool Player::RewardHonor(Unit *uVictim, uint32 groupsize, float honor, bool pvpt if(groupsize > 1) honor /= groupsize; + // apply honor multiplier from aura (not stacking-get highest) + honor = int32(float(honor) * (float(GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HONOR_GAIN_PCT))+100.0f)/100.0f); honor *= (((float)urand(8,12))/10); // approx honor: 80% - 120% of real honor } @@ -6198,8 +6328,8 @@ bool Player::RewardHonor(Unit *uVictim, uint32 groupsize, float honor, bool pvpt { // Check if allowed to receive it in current map uint8 MapType = sWorld.getConfig(CONFIG_PVP_TOKEN_MAP_TYPE); - if( (MapType == 1 && !InBattleGround() && !HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP)) - || (MapType == 2 && !HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP)) + if( (MapType == 1 && !InBattleGround() && !HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) + || (MapType == 2 && !HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) || (MapType == 3 && !InBattleGround()) ) return true; @@ -6257,24 +6387,18 @@ void Player::ModifyArenaPoints( int32 value ) uint32 Player::GetGuildIdFromDB(uint64 guid) { - std::ostringstream ss; - ss<<"SELECT guildid FROM guild_member WHERE guid='"<<guid<<"'"; - QueryResult *result = CharacterDatabase.Query( ss.str().c_str() ); - if( result ) - { - uint32 v = result->Fetch()[0].GetUInt32(); - delete result; - return v; - } - else + QueryResult* result = CharacterDatabase.PQuery("SELECT guildid FROM guild_member WHERE guid='%u'", GUID_LOPART(guid)); + if(!result) return 0; + + uint32 id = result->Fetch()[0].GetUInt32(); + delete result; + return id; } uint32 Player::GetRankFromDB(uint64 guid) { - std::ostringstream ss; - ss<<"SELECT rank FROM guild_member WHERE guid='"<<guid<<"'"; - QueryResult *result = CharacterDatabase.Query( ss.str().c_str() ); + QueryResult *result = CharacterDatabase.PQuery( "SELECT rank FROM guild_member WHERE guid='%u'", GUID_LOPART(guid) ); if( result ) { uint32 v = result->Fetch()[0].GetUInt32(); @@ -6298,10 +6422,8 @@ uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type) uint32 Player::GetZoneIdFromDB(uint64 guid) { - std::ostringstream ss; - - ss<<"SELECT zone FROM characters WHERE guid='"<<GUID_LOPART(guid)<<"'"; - QueryResult *result = CharacterDatabase.Query( ss.str().c_str() ); + uint32 guidLow = GUID_LOPART(guid); + QueryResult *result = CharacterDatabase.PQuery( "SELECT zone FROM characters WHERE guid='%u'", guidLow ); if (!result) return 0; Field* fields = result->Fetch(); @@ -6311,22 +6433,19 @@ uint32 Player::GetZoneIdFromDB(uint64 guid) if (!zone) { // stored zone is zero, use generic and slow zone detection - ss.str(""); - ss<<"SELECT map,position_x,position_y FROM characters WHERE guid='"<<GUID_LOPART(guid)<<"'"; - result = CharacterDatabase.Query(ss.str().c_str()); + result = CharacterDatabase.PQuery("SELECT map,position_x,position_y,position_z FROM characters WHERE guid='%u'", guidLow); if( !result ) return 0; fields = result->Fetch(); - uint32 map = fields[0].GetUInt32(); + uint32 map = fields[0].GetUInt32(); float posx = fields[1].GetFloat(); float posy = fields[2].GetFloat(); + float posz = fields[3].GetFloat(); delete result; - zone = MapManager::Instance().GetZoneId(map,posx,posy); + zone = MapManager::Instance().GetZoneId(map,posx,posy,posz); - ss.str(""); - ss << "UPDATE characters SET zone='"<<zone<<"' WHERE guid='"<<GUID_LOPART(guid)<<"'"; - CharacterDatabase.Execute(ss.str().c_str()); + CharacterDatabase.PExecute("UPDATE characters SET zone='%u' WHERE guid='%u'", zone, guidLow); } return zone; @@ -6343,14 +6462,14 @@ void Player::UpdateArea(uint32 newArea) if(area && (area->flags & AREA_FLAG_ARENA)) { if(!isGameMaster()) - SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); + SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); } else { // remove ffa flag only if not ffapvp realm // removal in sanctuaries and capitals is handled in zone update - if(HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP) && !sWorld.IsFFAPvPRealm()) - RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); + if(HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) && !sWorld.IsFFAPvPRealm()) + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); } UpdateAreaDependentAuras(newArea); @@ -6412,13 +6531,13 @@ void Player::UpdateZone(uint32 newZone) if(zone->flags & AREA_FLAG_SANCTUARY) // in sanctuary { - SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY); + SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY); if(sWorld.IsFFAPvPRealm()) - RemoveFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); } else { - RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY); + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY); } if(zone->flags & AREA_FLAG_CAPITAL) // in capital city @@ -6428,7 +6547,7 @@ void Player::UpdateZone(uint32 newZone) InnEnter(time(0),GetMapId(),0,0,0); if(sWorld.IsFFAPvPRealm()) - RemoveFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); } else // anywhere else { @@ -6442,7 +6561,7 @@ void Player::UpdateZone(uint32 newZone) SetRestType(REST_TYPE_NO); if(sWorld.IsFFAPvPRealm()) - SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); } } else // not in tavern (leave city then) @@ -6452,7 +6571,7 @@ void Player::UpdateZone(uint32 newZone) // Set player to FFA PVP when not in rested environment. if(sWorld.IsFFAPvPRealm()) - SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); + SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); } } } @@ -6622,7 +6741,12 @@ void Player::_ApplyItemMods(Item *item, uint8 slot,bool apply) sLog.outDetail("applying mods for item %u ",item->GetGUIDLow()); - uint32 attacktype = Player::GetAttackBySlot(slot); + uint8 attacktype = Player::GetAttackBySlot(slot); + + //check disarm only on mod apply to allow remove item mods + if (apply && !CanUseAttackType(attacktype) ) + return; + if(attacktype < MAX_ATTACK) _ApplyWeaponDependentAuraMods(item,WeaponAttackType(attacktype),apply); @@ -6640,19 +6764,43 @@ void Player::_ApplyItemMods(Item *item, uint8 slot,bool apply) sLog.outDebug("_ApplyItemMods complete."); } -void Player::_ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply) +void Player::_ApplyItemBonuses(ItemPrototype const *proto, uint8 slot, bool apply) { if(slot >= INVENTORY_SLOT_BAG_END || !proto) return; for (int i = 0; i < 10; i++) { - float val = float (proto->ItemStat[i].ItemStatValue); + uint32 statType = 0; + int32 val = 0; - if(val==0) + if(proto->ScalingStatDistribution) + { + if(ScalingStatDistributionEntry const *ssd = sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution)) + { + statType = ssd->StatMod[i]; + + if(uint32 modifier = ssd->Modifier[i]) + { + uint32 level = ((getLevel() > ssd->MaxLevel) ? ssd->MaxLevel : getLevel()); + if(ScalingStatValuesEntry const *ssv = sScalingStatValuesStore.LookupEntry(level)) + { + uint32 multiplier = ssv->Multiplier[proto->GetScalingStatValuesColumn()]; + val = (multiplier * modifier) / 10000; + } + } + } + } + else + { + statType = proto->ItemStat[i].ItemStatType; + val = proto->ItemStat[i].ItemStatValue; + } + + if(val == 0) continue; - switch (proto->ItemStat[i].ItemStatType) + switch (statType) { case ITEM_MOD_MANA: HandleStatModifier(UNIT_MOD_MANA, BASE_VALUE, float(val), apply); @@ -6770,6 +6918,32 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply) case ITEM_MOD_EXPERTISE_RATING: ApplyRatingMod(CR_EXPERTISE, int32(val), apply); break; + case ITEM_MOD_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(val), apply); + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); + break; + case ITEM_MOD_RANGED_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(val), apply); + break; + case ITEM_MOD_FERAL_ATTACK_POWER: + ApplyFeralAPBonus(int32(val), apply); + break; + case ITEM_MOD_SPELL_HEALING_DONE: + ApplySpellHealingBonus(int32(val), apply); + break; + case ITEM_MOD_SPELL_DAMAGE_DONE: + ApplySpellDamageBonus(int32(val), apply); + break; + case ITEM_MOD_MANA_REGENERATION: + ApplyManaRegenBonus(int32(val), apply); + break; + case ITEM_MOD_ARMOR_PENETRATION_RATING: + ApplyRatingMod(CR_ARMOR_PENETRATION, int32(val), apply); + break; + case ITEM_MOD_SPELL_POWER: + ApplySpellHealingBonus(int32(val), apply); + ApplySpellDamageBonus(int32(val), apply); + break; } } @@ -6824,7 +6998,15 @@ void Player::_ApplyItemBonuses(ItemPrototype const *proto,uint8 slot,bool apply) SetBaseWeaponDamage(attType, MAXDAMAGE, damage); } - if(!IsUseEquipedWeapon(slot==EQUIPMENT_SLOT_MAINHAND)) + // Druids get feral AP bonus from weapon dps + if(getClass() == CLASS_DRUID) + { + int32 feral_bonus = proto->getFeralBonus(); + if (feral_bonus > 0) + ApplyFeralAPBonus(feral_bonus, apply); + } + + if(IsInFeralForm() || !CanUseAttackType(attType)) return; if (proto->Delay) @@ -6873,7 +7055,7 @@ void Player::_ApplyWeaponDependentAuraCritMod(Item *item, WeaponAttackType attac if (item->IsFitToSpellRequirements(aura->GetSpellProto())) { - HandleBaseModValue(mod, FLAT_MOD, float (aura->GetModifierValue()), apply); + HandleBaseModValue(mod, FLAT_MOD, float (aura->GetModifier()->m_amount), apply); } } @@ -6907,7 +7089,7 @@ void Player::_ApplyWeaponDependentAuraDamageMod(Item *item, WeaponAttackType att if (item->IsFitToSpellRequirements(aura->GetSpellProto())) { - HandleStatModifier(unitMod, unitModType, float(aura->GetModifierValue()),apply); + HandleStatModifier(unitMod, unitModType, float(aura->GetModifier()->m_amount),apply); } } @@ -7102,6 +7284,92 @@ void Player::CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attTy } } +void Player::CastItemUseSpell(Item *item,SpellCastTargets const& targets,uint8 cast_count, uint32 glyphIndex) +{ + ItemPrototype const* proto = item->GetProto(); + // special learning case + if(proto->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN || proto->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN_PET) + { + uint32 learn_spell_id = proto->Spells[0].SpellId; + uint32 learning_spell_id = proto->Spells[1].SpellId; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(learn_spell_id); + if(!spellInfo) + { + sLog.outError("Player::CastItemUseSpell: Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, learn_spell_id); + SendEquipError(EQUIP_ERR_NONE,item,NULL); + return; + } + + Spell *spell = new Spell(this, spellInfo, false); + spell->m_CastItem = item; + spell->m_cast_count = cast_count; //set count of casts + spell->m_currentBasePoints[0] = learning_spell_id; + spell->prepare(&targets); + return; + } + + // use triggered flag only for items with many spell casts and for not first cast + int count = 0; + + // item spells casted at use + for(int i = 0; i < 5; ++i) + { + _Spell const& spellData = proto->Spells[i]; + + // no spell + if(!spellData.SpellId) + continue; + + // wrong triggering type + if( spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) + continue; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId); + if(!spellInfo) + { + sLog.outError("Player::CastItemUseSpell: Item (Entry: %u) in have wrong spell id %u, ignoring",proto->ItemId, spellData.SpellId); + continue; + } + + Spell *spell = new Spell(this, spellInfo, (count > 0)); + spell->m_CastItem = item; + spell->m_cast_count = cast_count; // set count of casts + spell->m_glyphIndex = glyphIndex; // glyph index + spell->prepare(&targets); + + ++count; + } + + // Item enchantments spells casted at use + for(int e_slot = 0; e_slot < MAX_ENCHANTMENT_SLOT; ++e_slot) + { + uint32 enchant_id = item->GetEnchantmentId(EnchantmentSlot(e_slot)); + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) continue; + for (int s=0;s<3;s++) + { + if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_USE_SPELL) + continue; + + SpellEntry const *spellInfo = sSpellStore.LookupEntry(pEnchant->spellid[s]); + if (!spellInfo) + { + sLog.outError("Player::CastItemUseSpell Enchant %i, cast unknown spell %i", pEnchant->ID, pEnchant->spellid[s]); + continue; + } + + Spell *spell = new Spell(this, spellInfo, (count > 0)); + spell->m_CastItem = item; + spell->m_cast_count = cast_count; // set count of casts + spell->m_glyphIndex = glyphIndex; // glyph index + spell->prepare(&targets); + + ++count; + } + } +} + void Player::_RemoveAllItemMods() { sLog.outDebug("_RemoveAllItemMods start."); @@ -7277,7 +7545,7 @@ void Player::RemovedInsignia(Player* looterPlr) // We have to convert player corpse to bones, not to be able to resurrect there // SpawnCorpseBones isn't handy, 'cos it saves player while he in BG - Corpse *bones = ObjectAccessor::Instance().ConvertCorpseForPlayer(GetGUID()); + Corpse *bones = ObjectAccessor::Instance().ConvertCorpseForPlayer(GetGUID(),true); if (!bones) return; @@ -7344,11 +7612,11 @@ void Player::SendLoot(uint64 guid, LootType loot_type) { sLog.outDebug(" if(lootid)"); loot->clear(); - loot->FillLoot(lootid, LootTemplates_Gameobject, this); + loot->FillLoot(lootid, LootTemplates_Gameobject, this, false); } if(loot_type == LOOT_FISHING) - go->getFishLoot(loot); + go->getFishLoot(loot,this); go->SetLootState(GO_ACTIVATED); } @@ -7371,7 +7639,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) { item->m_lootGenerated = true; loot->clear(); - loot->FillLoot(item->GetProto()->DisenchantID, LootTemplates_Disenchant, this); + loot->FillLoot(item->GetProto()->DisenchantID, LootTemplates_Disenchant, this,true); } } else if(loot_type == LOOT_PROSPECTING) @@ -7382,7 +7650,18 @@ void Player::SendLoot(uint64 guid, LootType loot_type) { item->m_lootGenerated = true; loot->clear(); - loot->FillLoot(item->GetEntry(), LootTemplates_Prospecting, this); + loot->FillLoot(item->GetEntry(), LootTemplates_Prospecting, this,true); + } + } + else if(loot_type == LOOT_MILLING) + { + loot = &item->loot; + + if(!item->m_lootGenerated) + { + item->m_lootGenerated = true; + loot->clear(); + loot->FillLoot(item->GetEntry(), LootTemplates_Milling, this,true); } } else @@ -7393,7 +7672,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) { item->m_lootGenerated = true; loot->clear(); - loot->FillLoot(item->GetEntry(), LootTemplates_Item, this); + loot->FillLoot(item->GetEntry(), LootTemplates_Item, this,true); loot->generateMoneyLoot(item->GetProto()->MinMoneyLoot,item->GetProto()->MaxMoneyLoot); } @@ -7417,7 +7696,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) uint32 pLevel = bones->loot.gold; bones->loot.clear(); if(GetBattleGround()->GetTypeID() == BATTLEGROUND_AV) - loot->FillLoot(1, LootTemplates_Creature, this); + loot->FillLoot(1, LootTemplates_Creature, this, true); // It may need a better formula // Now it works like this: lvl10: ~6copper, lvl70: ~9silver bones->loot.gold = (uint32)( urand(50, 150) * 0.016f * pow( ((float)pLevel)/5.76f, 2.5f) * sWorld.getRate(RATE_DROP_MONEY) ); @@ -7453,7 +7732,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) loot->clear(); if (uint32 lootid = creature->GetCreatureInfo()->pickpocketLootId) - loot->FillLoot(lootid, LootTemplates_Pickpocketing, this); + loot->FillLoot(lootid, LootTemplates_Pickpocketing, this, false); // Generate extra money for pick pocket loot const uint32 a = urand(0, creature->getLevel()/2); @@ -7483,7 +7762,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) loot->clear(); if (uint32 lootid = creature->GetCreatureInfo()->lootid) - loot->FillLoot(lootid, LootTemplates_Creature, recipient); + loot->FillLoot(lootid, LootTemplates_Creature, recipient, false); loot->generateMoneyLoot(creature->GetCreatureInfo()->mingold,creature->GetCreatureInfo()->maxgold); @@ -7513,7 +7792,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) if (loot_type == LOOT_SKINNING) { loot->clear(); - loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, this); + loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, this, false); } // set group rights only for loot_type != LOOT_SKINNING else @@ -7547,41 +7826,8 @@ void Player::SendLoot(uint64 guid, LootType loot_type) SetLootGUID(guid); - QuestItemList *q_list = 0; - if (permission != NONE_PERMISSION) - { - QuestItemMap const& lootPlayerQuestItems = loot->GetPlayerQuestItems(); - QuestItemMap::const_iterator itr = lootPlayerQuestItems.find(GetGUIDLow()); - if (itr == lootPlayerQuestItems.end()) - q_list = loot->FillQuestLoot(this); - else - q_list = itr->second; - } - - QuestItemList *ffa_list = 0; - if (permission != NONE_PERMISSION) - { - QuestItemMap const& lootPlayerFFAItems = loot->GetPlayerFFAItems(); - QuestItemMap::const_iterator itr = lootPlayerFFAItems.find(GetGUIDLow()); - if (itr == lootPlayerFFAItems.end()) - ffa_list = loot->FillFFALoot(this); - else - ffa_list = itr->second; - } - - QuestItemList *conditional_list = 0; - if (permission != NONE_PERMISSION) - { - QuestItemMap const& lootPlayerNonQuestNonFFAConditionalItems = loot->GetPlayerNonQuestNonFFAConditionalItems(); - QuestItemMap::const_iterator itr = lootPlayerNonQuestNonFFAConditionalItems.find(GetGUIDLow()); - if (itr == lootPlayerNonQuestNonFFAConditionalItems.end()) - conditional_list = loot->FillNonQuestNonFFAConditionalLoot(this); - else - conditional_list = itr->second; - } - - // LOOT_PICKPOCKETING, LOOT_PROSPECTING, LOOT_DISENCHANTING and LOOT_INSIGNIA unsupported by client, sending LOOT_SKINNING instead - if(loot_type == LOOT_PICKPOCKETING || loot_type == LOOT_DISENCHANTING || loot_type == LOOT_PROSPECTING || loot_type == LOOT_INSIGNIA) + // LOOT_PICKPOCKETING, LOOT_PROSPECTING, LOOT_DISENCHANTING, LOOT_INSIGNIA and LOOT_MILLING unsupported by client, sending LOOT_SKINNING instead + if(loot_type == LOOT_PICKPOCKETING || loot_type == LOOT_DISENCHANTING || loot_type == LOOT_PROSPECTING || loot_type == LOOT_INSIGNIA || loot_type == LOOT_MILLING) loot_type = LOOT_SKINNING; if(loot_type == LOOT_FISHINGHOLE) @@ -7591,7 +7837,7 @@ void Player::SendLoot(uint64 guid, LootType loot_type) data << uint64(guid); data << uint8(loot_type); - data << LootView(*loot, q_list, ffa_list, conditional_list, this, permission); + data << LootView(*loot, this, permission); SendDirectMessage(&data); @@ -7658,46 +7904,46 @@ void Player::SendInitWorldStates(bool forceZone, uint32 forceZoneId) case 1537: case 2257: case 2918: - NumberOfFields = 6; + NumberOfFields = 8; break; case 139: - NumberOfFields = 39; + NumberOfFields = 41; break; case 1377: - NumberOfFields = 13; + NumberOfFields = 15; break; case 2597: - NumberOfFields = 81; + NumberOfFields = 83; break; case 3277: - NumberOfFields = 14; + NumberOfFields = 16; break; case 3358: case 3820: - NumberOfFields = 38; + NumberOfFields = 40; break; case 3483: - NumberOfFields = 25; + NumberOfFields = 27; break; case 3518: - NumberOfFields = 37; + NumberOfFields = 39; break; case 3519: - NumberOfFields = 36; + NumberOfFields = 38; break; case 3521: - NumberOfFields = 35; + NumberOfFields = 37; break; case 3698: case 3702: case 3968: - NumberOfFields = 9; + NumberOfFields = 11; break; case 3703: - NumberOfFields = 9; + NumberOfFields = 11; break; default: - NumberOfFields = 10; + NumberOfFields = 12; break; } @@ -7712,6 +7958,10 @@ void Player::SendInitWorldStates(bool forceZone, uint32 forceZoneId) data << uint32(0x8d5) << uint32(0x0); // 4 data << uint32(0x8d4) << uint32(0x0); // 5 data << uint32(0x8d3) << uint32(0x0); // 6 + // 7 1 - Arena season in progress, 0 - end of season + data << uint32(0xC77) << uint32(sWorld.getConfig(CONFIG_ARENA_SEASON_IN_PROGRESS)); + // 8 Arena season id + data << uint32(0xF3D) << uint32(sWorld.getConfig(CONFIG_ARENA_SEASON_ID)); if(mapid == 530) // Outland { data << uint32(0x9bf) << uint32(0x0); // 7 @@ -8305,7 +8555,8 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap // (this will be replace mainhand weapon at auto equip instead unwonted "you don't known dual wielding" ... if(CanDualWield()) slots[1] = EQUIPMENT_SLOT_OFFHAND; - };break; + break; + }; case INVTYPE_SHIELD: slots[0] = EQUIPMENT_SLOT_OFFHAND; break; @@ -8314,6 +8565,8 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap break; case INVTYPE_2HWEAPON: slots[0] = EQUIPMENT_SLOT_MAINHAND; + if (CanDualWield() && CanTitanGrip()) + slots[1] = EQUIPMENT_SLOT_OFFHAND; break; case INVTYPE_TABARD: slots[0] = EQUIPMENT_SLOT_TABARD; @@ -8359,6 +8612,10 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap if (pClass == CLASS_WARLOCK) slots[0] = EQUIPMENT_SLOT_RANGED; break; + case ITEM_SUBCLASS_ARMOR_SIGIL: + if (pClass == CLASS_DEATH_KNIGHT) + slots[0] = EQUIPMENT_SLOT_RANGED; + break; } break; } @@ -8384,14 +8641,8 @@ uint8 Player::FindEquipSlot( ItemPrototype const* proto, uint32 slot, bool swap { if ( slots[i] != NULL_SLOT && !GetItemByPos( INVENTORY_SLOT_BAG_0, slots[i] ) ) { - // in case 2hand equipped weapon offhand slot empty but not free - if(slots[i]==EQUIPMENT_SLOT_OFFHAND) - { - Item* mainItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND ); - if(!mainItem || mainItem->GetProto()->InventoryType != INVTYPE_2HWEAPON) - return slots[i]; - } - else + // in case 2hand equipped weapon (without titan grip) offhand slot empty but not free + if(slots[i]!=EQUIPMENT_SLOT_OFFHAND || !IsTwoHandUsed()) return slots[i]; } } @@ -8441,7 +8692,7 @@ uint8 Player::CanUnequipItems( uint32 item, uint32 count ) const return EQUIP_ERR_OK; } } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->GetEntry() == item ) @@ -8483,7 +8734,7 @@ uint32 Player::GetItemCount( uint32 item, bool inBankAlso, Item* skipItem ) cons if( pItem && pItem != skipItem && pItem->GetEntry() == item ) count += pItem->GetCount(); } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem != skipItem && pItem->GetEntry() == item ) @@ -8543,7 +8794,7 @@ Item* Player::GetItemByGuid( uint64 guid ) const if( pItem && pItem->GetGUID() == guid ) return pItem; } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->GetGUID() == guid ) @@ -8589,7 +8840,7 @@ Item* Player::GetItemByPos( uint16 pos ) const Item* Player::GetItemByPos( uint8 bag, uint8 slot ) const { - if( bag == INVENTORY_SLOT_BAG_0 && ( slot < BANK_SLOT_BAG_END || slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END ) ) + if( bag == INVENTORY_SLOT_BAG_0 && ( slot < BANK_SLOT_BAG_END || slot >= KEYRING_SLOT_START && slot < QUESTBAG_SLOT_END ) ) return m_items[slot]; else if(bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END || bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END ) @@ -8612,14 +8863,14 @@ Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool useable) cons default: return NULL; } - Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, slot); + Item* item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, slot); if (!item || item->GetProto()->Class != ITEM_CLASS_WEAPON) return NULL; if(!useable) return item; - if( item->IsBroken() || !IsUseEquipedWeapon(attackType==BASE_ATTACK) ) + if( item->IsBroken() || IsInFeralForm()) return NULL; return item; @@ -8627,7 +8878,7 @@ Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool useable) cons Item* Player::GetShield(bool useable) const { - Item* item = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + Item* item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); if (!item || item->GetProto()->Class != ITEM_CLASS_ARMOR) return NULL; @@ -8640,7 +8891,7 @@ Item* Player::GetShield(bool useable) const return item; } -uint32 Player::GetAttackBySlot( uint8 slot ) +uint8 Player::GetAttackBySlot( uint8 slot ) { switch(slot) { @@ -8667,7 +8918,7 @@ bool Player::IsInventoryPos( uint8 bag, uint8 slot ) return true; if( bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END ) return true; - if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END ) ) + if( bag == INVENTORY_SLOT_BAG_0 && ( slot >= KEYRING_SLOT_START && slot < QUESTBAG_SLOT_END ) ) return true; return false; } @@ -8788,7 +9039,7 @@ bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const return true; } } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { Item *pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->GetEntry() == item ) @@ -8886,12 +9137,12 @@ uint8 Player::_CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, } // no maximum - if(pProto->MaxCount == 0) + if(pProto->MaxCount <= 0) return EQUIP_ERR_OK; uint32 curcount = GetItemCount(pProto->ItemId,true,pItem); - if( curcount + count > pProto->MaxCount ) + if (curcount + count > uint32(pProto->MaxCount)) { if(no_space_count) *no_space_count = count +curcount - pProto->MaxCount; @@ -8906,13 +9157,13 @@ bool Player::HasItemTotemCategory( uint32 TotemCategory ) const Item *pItem; for(uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i) { - pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + pItem = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) return true; } - for(uint8 i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; ++i) + for(uint8 i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; ++i) { - pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + pItem = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) return true; } @@ -8922,7 +9173,7 @@ bool Player::HasItemTotemCategory( uint32 TotemCategory ) const { for(uint32 j = 0; j < pBag->GetBagSize(); ++j) { - pItem = GetItemByPos( i, j ); + pItem = GetUseableItemByPos( i, j ); if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) return true; } @@ -8950,6 +9201,18 @@ uint8 Player::_CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountV if(slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_START+GetMaxKeyringSize() && !(pProto->BagFamily & BAG_FAMILY_MASK_KEYS)) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + // vanitypet case (not use, vanity pets stored as spells) + if(slot >= VANITYPET_SLOT_START && slot < VANITYPET_SLOT_END) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + + // currencytoken case (disabled until proper implement) + if(slot >= CURRENCYTOKEN_SLOT_START && slot < CURRENCYTOKEN_SLOT_END && !(false /*pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS*/)) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + + // guestbag case (disabled until proper implement) + if(slot >= QUESTBAG_SLOT_START && slot < QUESTBAG_SLOT_END && !(false /*pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS*/)) + return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; + // prevent cheating if(slot >= BUYBACK_SLOT_START && slot < BUYBACK_SLOT_END || slot >= PLAYER_SLOT_END) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; @@ -8969,7 +9232,7 @@ uint8 Player::_CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountV } // non empty stack with space - need_space = pProto->Stackable; + need_space = pProto->GetMaxStackSize(); } // non empty slot, check item type else @@ -8979,10 +9242,11 @@ uint8 Player::_CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountV return EQUIP_ERR_ITEM_CANT_STACK; // check free space - if(pItem2->GetCount() >= pProto->Stackable) + if(pItem2->GetCount() >= pProto->GetMaxStackSize()) return EQUIP_ERR_ITEM_CANT_STACK; - need_space = pProto->Stackable - pItem2->GetCount(); + // free stack space or infinity + need_space = pProto->GetMaxStackSize() - pItem2->GetCount(); } if(need_space > count) @@ -9036,9 +9300,9 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy if( pItem2 ) { - if(pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->Stackable ) + if(pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->GetMaxStackSize()) { - uint32 need_space = pProto->Stackable - pItem2->GetCount(); + uint32 need_space = pProto->GetMaxStackSize() - pItem2->GetCount(); if(need_space > count) need_space = count; @@ -9055,7 +9319,7 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy } else { - uint32 need_space = pProto->Stackable; + uint32 need_space = pProto->GetMaxStackSize(); if(need_space > count) need_space = count; @@ -9093,9 +9357,9 @@ uint8 Player::_CanStoreItem_InInventorySlots( uint8 slot_begin, uint8 slot_end, if( pItem2 ) { - if(pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->Stackable ) + if(pItem2->GetEntry() == pProto->ItemId && pItem2->GetCount() < pProto->GetMaxStackSize()) { - uint32 need_space = pProto->Stackable - pItem2->GetCount(); + uint32 need_space = pProto->GetMaxStackSize() - pItem2->GetCount(); if(need_space > count) need_space = count; ItemPosCount newPosition = ItemPosCount((INVENTORY_SLOT_BAG_0 << 8) | j, need_space); @@ -9111,7 +9375,7 @@ uint8 Player::_CanStoreItem_InInventorySlots( uint8 slot_begin, uint8 slot_end, } else { - uint32 need_space = pProto->Stackable; + uint32 need_space = pProto->GetMaxStackSize(); if(need_space > count) need_space = count; @@ -9190,11 +9454,11 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3 if( bag != NULL_BAG ) { // search stack in bag for merge to - if( pProto->Stackable > 1 ) + if( pProto->Stackable != 1 ) { if( bag == INVENTORY_SLOT_BAG_0 ) // inventory { - res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,KEYRING_SLOT_END,dest,pProto,count,true,pItem,bag,slot); + res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,true,pItem,bag,slot); if(res!=EQUIP_ERR_OK) { if(no_space_count) @@ -9282,6 +9546,53 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3 } } + // Vanity pet case skipped as not used + + /* until proper implementation + else if(pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) + { + res = _CanStoreItem_InInventorySlots(CURRENCYTOKEN_SLOT_START,CURRENCYTOKEN_SLOT_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + */ + /* until proper implementation + else if(pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS) + { + res = _CanStoreItem_InInventorySlots(QUESTBAG_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + */ + res = _CanStoreItem_InInventorySlots(INVENTORY_SLOT_ITEM_START,INVENTORY_SLOT_ITEM_END,dest,pProto,count,false,pItem,bag,slot); if(res!=EQUIP_ERR_OK) { @@ -9328,9 +9639,9 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3 // not specific bag or have space for partly store only in specific bag // search stack for merge to - if( pProto->Stackable > 1 ) + if( pProto->Stackable != 1 ) { - res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,KEYRING_SLOT_END,dest,pProto,count,true,pItem,bag,slot); + res = _CanStoreItem_InInventorySlots(KEYRING_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,true,pItem,bag,slot); if(res!=EQUIP_ERR_OK) { if(no_space_count) @@ -9429,6 +9740,53 @@ uint8 Player::_CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, uint3 } } + // Vanity pet case skipped as not used + + /* until proper implementation + else if(false pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) + { + res = _CanStoreItem_InInventorySlots(CURRENCYTOKEN_SLOT_START,CURRENCYTOKEN_SLOT_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + */ + /* until proper implementation + else if(false pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS) + { + res = _CanStoreItem_InInventorySlots(QUESTBAG_SLOT_START,QUESTBAG_SLOT_END,dest,pProto,count,false,pItem,bag,slot); + if(res!=EQUIP_ERR_OK) + { + if(no_space_count) + *no_space_count = count + no_similar_count; + return res; + } + + if(count==0) + { + if(no_similar_count==0) + return EQUIP_ERR_OK; + + if(no_space_count) + *no_space_count = count + no_similar_count; + return EQUIP_ERR_CANT_CARRY_MORE_OF_THIS; + } + } + */ + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { res = _CanStoreItem_InBag(i,dest,pProto,count,false,false,pItem,bag,slot); @@ -9498,10 +9856,14 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const int inv_slot_items[INVENTORY_SLOT_ITEM_END-INVENTORY_SLOT_ITEM_START]; int inv_bags[INVENTORY_SLOT_BAG_END-INVENTORY_SLOT_BAG_START][MAX_BAG_SIZE]; int inv_keys[KEYRING_SLOT_END-KEYRING_SLOT_START]; + int inv_tokens[CURRENCYTOKEN_SLOT_END-CURRENCYTOKEN_SLOT_START]; + int inv_quests[QUESTBAG_SLOT_END-QUESTBAG_SLOT_START]; memset(inv_slot_items,0,sizeof(int)*(INVENTORY_SLOT_ITEM_END-INVENTORY_SLOT_ITEM_START)); memset(inv_bags,0,sizeof(int)*(INVENTORY_SLOT_BAG_END-INVENTORY_SLOT_BAG_START)*MAX_BAG_SIZE); memset(inv_keys,0,sizeof(int)*(KEYRING_SLOT_END-KEYRING_SLOT_START)); + memset(inv_tokens,0,sizeof(int)*(CURRENCYTOKEN_SLOT_END-CURRENCYTOKEN_SLOT_START)); + memset(inv_quests,0,sizeof(int)*(QUESTBAG_SLOT_END-QUESTBAG_SLOT_START)); for(int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; i++) { @@ -9523,6 +9885,28 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const } } + // Vanity pet case skipped as not used + + for(int i = CURRENCYTOKEN_SLOT_START; i < CURRENCYTOKEN_SLOT_END; i++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + + if (pItem2 && !pItem2->IsInTrade()) + { + inv_tokens[i-CURRENCYTOKEN_SLOT_START] = pItem2->GetCount(); + } + } + + for(int i = QUESTBAG_SLOT_START; i < QUESTBAG_SLOT_END; i++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); + + if (pItem2 && !pItem2->IsInTrade()) + { + inv_quests[i-QUESTBAG_SLOT_START] = pItem2->GetCount(); + } + } + for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) @@ -9566,14 +9950,14 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const return res; // search stack for merge to - if( pProto->Stackable > 1 ) + if( pProto->Stackable != 1 ) { bool b_found = false; for(int t = KEYRING_SLOT_START; t < KEYRING_SLOT_END; t++) { pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); - if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_keys[t-KEYRING_SLOT_START] + pItem->GetCount() <= pProto->Stackable ) + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_keys[t-KEYRING_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize()) { inv_keys[t-KEYRING_SLOT_START] += pItem->GetCount(); b_found = true; @@ -9582,10 +9966,36 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const } if (b_found) continue; + // Vanity pet case skipped as not used + + for(int t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; t++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_tokens[t-CURRENCYTOKEN_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize()) + { + inv_tokens[t-CURRENCYTOKEN_SLOT_START] += pItem->GetCount(); + b_found = true; + break; + } + } + if (b_found) continue; + + for(int t = QUESTBAG_SLOT_START; t < QUESTBAG_SLOT_END; t++) + { + pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_quests[t-QUESTBAG_SLOT_START] + pItem->GetCount() <= pProto->GetMaxStackSize()) + { + inv_quests[t-QUESTBAG_SLOT_START] += pItem->GetCount(); + b_found = true; + break; + } + } + if (b_found) continue; + for(int t = INVENTORY_SLOT_ITEM_START; t < INVENTORY_SLOT_ITEM_END; t++) { pItem2 = GetItemByPos( INVENTORY_SLOT_BAG_0, t ); - if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_slot_items[t-INVENTORY_SLOT_ITEM_START] + pItem->GetCount() <= pProto->Stackable ) + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_slot_items[t-INVENTORY_SLOT_ITEM_START] + pItem->GetCount() <= pProto->GetMaxStackSize()) { inv_slot_items[t-INVENTORY_SLOT_ITEM_START] += pItem->GetCount(); b_found = true; @@ -9602,7 +10012,7 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const for(uint32 j = 0; j < pBag->GetBagSize(); j++) { pItem2 = GetItemByPos( t, j ); - if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->Stackable ) + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->GetMaxStackSize()) { inv_bags[t-INVENTORY_SLOT_BAG_START][j] += pItem->GetCount(); b_found = true; @@ -9634,6 +10044,41 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const if (b_found) continue; + // Vanity pet case skipped as not used + + /* until proper implementation + if(pProto->BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) + { + for(uint32 t = CURRENCYTOKEN_SLOT_START; t < CURRENCYTOKEN_SLOT_END; ++t) + { + if( inv_tokens[t-CURRENCYTOKEN_SLOT_START] == 0 ) + { + inv_tokens[t-CURRENCYTOKEN_SLOT_START] = 1; + b_found = true; + break; + } + } + } + + if (b_found) continue; + */ + /* until proper implementation + if(pProto->BagFamily & BAG_FAMILY_MASK_QUEST_ITEMS) + { + for(uint32 t = QUESTBAG_SLOT_START; t < QUESTBAG_SLOT_END; ++t) + { + if( inv_quests[t-QUESTBAG_SLOT_START] == 0 ) + { + inv_quests[t-QUESTBAG_SLOT_START] = 1; + b_found = true; + break; + } + } + } + + if (b_found) continue; + */ + for(int t = INVENTORY_SLOT_BAG_START; !b_found && t < INVENTORY_SLOT_BAG_END; t++) { pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t ); @@ -9819,33 +10264,42 @@ uint8 Player::CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bo if(eslot == EQUIPMENT_SLOT_OFFHAND) { - if( type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND ) + if (type == INVTYPE_WEAPON || type == INVTYPE_WEAPONOFFHAND) { if(!CanDualWield()) return EQUIP_ERR_CANT_DUAL_WIELD; } - - Item *mainItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND ); - if(mainItem) + else if (type == INVTYPE_2HWEAPON) { - if(mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON) - return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED; + if(!CanDualWield() || !CanTitanGrip()) + return EQUIP_ERR_CANT_DUAL_WIELD; } + + if(IsTwoHandUsed()) + return EQUIP_ERR_CANT_EQUIP_WITH_TWOHANDED; } // equip two-hand weapon case (with possible unequip 2 items) if( type == INVTYPE_2HWEAPON ) { - if(eslot != EQUIPMENT_SLOT_MAINHAND) + if (eslot == EQUIPMENT_SLOT_OFFHAND) + { + if (!CanTitanGrip()) + return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED; + } + else if (eslot != EQUIPMENT_SLOT_MAINHAND) return EQUIP_ERR_ITEM_CANT_BE_EQUIPPED; - // offhand item must can be stored in inventory for offhand item and it also must be unequipped - Item *offItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND ); - ItemPosCountVec off_dest; - if( offItem && (!not_loading || - CanUnequipItem(uint16(INVENTORY_SLOT_BAG_0) << 8 | EQUIPMENT_SLOT_OFFHAND,false) != EQUIP_ERR_OK || - CanStoreItem( NULL_BAG, NULL_SLOT, off_dest, offItem, false ) != EQUIP_ERR_OK ) ) - return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_INVENTORY_FULL; + if (!CanTitanGrip()) + { + // offhand item must can be stored in inventory for offhand item and it also must be unequipped + Item *offItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND ); + ItemPosCountVec off_dest; + if( offItem && (!not_loading || + CanUnequipItem(uint16(INVENTORY_SLOT_BAG_0) << 8 | EQUIPMENT_SLOT_OFFHAND,false) != EQUIP_ERR_OK || + CanStoreItem( NULL_BAG, NULL_SLOT, off_dest, offItem, false ) != EQUIP_ERR_OK ) ) + return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_INVENTORY_FULL; + } } dest = ((INVENTORY_SLOT_BAG_0 << 8) | eslot); return EQUIP_ERR_OK; @@ -9917,29 +10371,17 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p // in specific slot if( bag != NULL_BAG && slot != NULL_SLOT ) { - if( pProto->InventoryType == INVTYPE_BAG ) + if( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END ) { - Bag *pBag = (Bag*)pItem; - if( pBag ) - { - if( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END ) - { - if( !HasBankBagSlot( slot ) ) - return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT; - if( uint8 cantuse = CanUseItem( pItem, not_loading ) != EQUIP_ERR_OK ) - return cantuse; - } - else - { - if( !pBag->IsEmpty() ) - return EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG; - } - } - } - else - { - if( slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END ) + if (!pItem->IsBag()) return EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT; + + Bag *pBag = (Bag*)pItem; + if( !HasBankBagSlot( slot ) ) + return EQUIP_ERR_MUST_PURCHASE_THAT_BAG_SLOT; + + if( uint8 cantuse = CanUseItem( pItem, not_loading ) != EQUIP_ERR_OK ) + return cantuse; } res = _CanStoreItem_InSpecificSlot(bag,slot,dest,pProto,count,swap,pItem); @@ -9963,7 +10405,7 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p } // search stack in bag for merge to - if( pProto->Stackable > 1 ) + if( pProto->Stackable != 1 ) { if( bag == INVENTORY_SLOT_BAG_0 ) { @@ -10015,7 +10457,7 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p // not specific bag or have space for partly store only in specific bag // search stack for merge to - if( pProto->Stackable > 1 ) + if( pProto->Stackable != 1 ) { // in slots res = _CanStoreItem_InInventorySlots(BANK_SLOT_ITEM_START,BANK_SLOT_ITEM_END,dest,pProto,count,true,pItem,bag,slot); @@ -10765,7 +11207,7 @@ void Player::DestroyItemCount( uint32 item, uint32 count, bool update, bool uneq } } } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->GetEntry() == item ) @@ -10868,7 +11310,7 @@ void Player::DestroyZoneLimitedItem( bool update, uint32 new_zone ) if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) DestroyItem( INVENTORY_SLOT_BAG_0, i, update); } - for(int i = KEYRING_SLOT_START; i < KEYRING_SLOT_END; i++) + for(int i = KEYRING_SLOT_START; i < QUESTBAG_SLOT_END; i++) { Item* pItem = GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) @@ -11096,6 +11538,8 @@ void Player::SwapItem( uint16 src, uint16 dst ) return; } + // SRC checks + if(pSrcItem->m_lootGenerated) // prevent swap looting item { //best error message found for attempting to swap while looting @@ -11106,8 +11550,8 @@ void Player::SwapItem( uint16 src, uint16 dst ) // check unequip potability for equipped items and bank bags if(IsEquipmentPos ( src ) || IsBagPos ( src )) { - // bags can be swapped with empty bag slots - uint8 msg = CanUnequipItem( src, !IsBagPos ( src ) || IsBagPos ( dst )); + // bags can be swapped with empty bag slots, or with empty bag (items move possibility checked later) + uint8 msg = CanUnequipItem( src, !IsBagPos ( src ) || IsBagPos ( dst ) || pDstItem && pDstItem->IsBag() && ((Bag*)pDstItem)->IsEmpty()); if(msg != EQUIP_ERR_OK) { SendEquipError( msg, pSrcItem, pDstItem ); @@ -11122,6 +11566,34 @@ void Player::SwapItem( uint16 src, uint16 dst ) return; } + // DST checks + + if (pDstItem) + { + if(pDstItem->m_lootGenerated) // prevent swap looting item + { + //best error message found for attempting to swap while looting + SendEquipError( EQUIP_ERR_CANT_DO_RIGHT_NOW, pDstItem, NULL ); + return; + } + + // check unequip potability for equipped items and bank bags + if(IsEquipmentPos ( dst ) || IsBagPos ( dst )) + { + // bags can be swapped with empty bag slots, or with empty bag (items move possibility checked later) + uint8 msg = CanUnequipItem( dst, !IsBagPos ( dst ) || IsBagPos ( src ) || pSrcItem->IsBag() && ((Bag*)pSrcItem)->IsEmpty()); + if(msg != EQUIP_ERR_OK) + { + SendEquipError( msg, pSrcItem, pDstItem ); + return; + } + } + } + + // NOW this is or item move (swap with empty), or swap with another item (including bags in bag possitions) + // or swap empty bag with another empty or not empty bag (with items exchange) + + // Move case if( !pDstItem ) { if( IsInventoryPos( dst ) ) @@ -11164,140 +11636,187 @@ void Player::SwapItem( uint16 src, uint16 dst ) EquipItem( dest, pSrcItem, true); AutoUnequipOffhandIfNeed(); } + + return; } - else // if (!pDstItem) + + // attempt merge to / fill target item + if(!pSrcItem->IsBag() && !pDstItem->IsBag()) { - if(pDstItem->m_lootGenerated) // prevent swap looting item - { - //best error message found for attempting to swap while looting - SendEquipError( EQUIP_ERR_CANT_DO_RIGHT_NOW, pDstItem, NULL ); + uint8 msg; + ItemPosCountVec sDest; + uint16 eDest; + if( IsInventoryPos( dst ) ) + msg = CanStoreItem( dstbag, dstslot, sDest, pSrcItem, false ); + else if( IsBankPos ( dst ) ) + msg = CanBankItem( dstbag, dstslot, sDest, pSrcItem, false ); + else if( IsEquipmentPos ( dst ) ) + msg = CanEquipItem( dstslot, eDest, pSrcItem, false ); + else return; - } - // check unequip potability for equipped items and bank bags - if(IsEquipmentPos ( dst ) || IsBagPos ( dst )) + // can be merge/fill + if(msg == EQUIP_ERR_OK) { - // bags can be swapped with empty bag slots - uint8 msg = CanUnequipItem( dst, !IsBagPos ( dst ) || IsBagPos ( src ) ); - if(msg != EQUIP_ERR_OK) + if( pSrcItem->GetCount() + pDstItem->GetCount() <= pSrcItem->GetProto()->GetMaxStackSize()) { - SendEquipError( msg, pSrcItem, pDstItem ); - return; - } - } - - // attempt merge to / fill target item - { - uint8 msg; - ItemPosCountVec sDest; - uint16 eDest; - if( IsInventoryPos( dst ) ) - msg = CanStoreItem( dstbag, dstslot, sDest, pSrcItem, false ); - else if( IsBankPos ( dst ) ) - msg = CanBankItem( dstbag, dstslot, sDest, pSrcItem, false ); - else if( IsEquipmentPos ( dst ) ) - msg = CanEquipItem( dstslot, eDest, pSrcItem, false ); - else - return; + RemoveItem(srcbag, srcslot, true); - // can be merge/fill - if(msg == EQUIP_ERR_OK) - { - if( pSrcItem->GetCount() + pDstItem->GetCount() <= pSrcItem->GetProto()->Stackable ) + if( IsInventoryPos( dst ) ) + StoreItem( sDest, pSrcItem, true); + else if( IsBankPos ( dst ) ) + BankItem( sDest, pSrcItem, true); + else if( IsEquipmentPos ( dst ) ) { - RemoveItem(srcbag, srcslot, true); - - if( IsInventoryPos( dst ) ) - StoreItem( sDest, pSrcItem, true); - else if( IsBankPos ( dst ) ) - BankItem( sDest, pSrcItem, true); - else if( IsEquipmentPos ( dst ) ) - { - EquipItem( eDest, pSrcItem, true); - AutoUnequipOffhandIfNeed(); - } + EquipItem( eDest, pSrcItem, true); + AutoUnequipOffhandIfNeed(); } - else + } + else + { + pSrcItem->SetCount( pSrcItem->GetCount() + pDstItem->GetCount() - pSrcItem->GetProto()->GetMaxStackSize()); + pDstItem->SetCount( pSrcItem->GetProto()->GetMaxStackSize()); + pSrcItem->SetState(ITEM_CHANGED, this); + pDstItem->SetState(ITEM_CHANGED, this); + if( IsInWorld() ) { - pSrcItem->SetCount( pSrcItem->GetCount() + pDstItem->GetCount() - pSrcItem->GetProto()->Stackable ); - pDstItem->SetCount( pSrcItem->GetProto()->Stackable ); - pSrcItem->SetState(ITEM_CHANGED, this); - pDstItem->SetState(ITEM_CHANGED, this); - if( IsInWorld() ) - { - pSrcItem->SendUpdateToPlayer( this ); - pDstItem->SendUpdateToPlayer( this ); - } + pSrcItem->SendUpdateToPlayer( this ); + pDstItem->SendUpdateToPlayer( this ); } - return; } + return; } + } - // impossible merge/fill, do real swap - uint8 msg; + // impossible merge/fill, do real swap + uint8 msg; - // check src->dest move possibility - ItemPosCountVec sDest; - uint16 eDest; - if( IsInventoryPos( dst ) ) - msg = CanStoreItem( dstbag, dstslot, sDest, pSrcItem, true ); - else if( IsBankPos( dst ) ) - msg = CanBankItem( dstbag, dstslot, sDest, pSrcItem, true ); - else if( IsEquipmentPos( dst ) ) - { - msg = CanEquipItem( dstslot, eDest, pSrcItem, true ); - if( msg == EQUIP_ERR_OK ) - msg = CanUnequipItem( eDest, true ); - } + // check src->dest move possibility + ItemPosCountVec sDest; + uint16 eDest; + if( IsInventoryPos( dst ) ) + msg = CanStoreItem( dstbag, dstslot, sDest, pSrcItem, true ); + else if( IsBankPos( dst ) ) + msg = CanBankItem( dstbag, dstslot, sDest, pSrcItem, true ); + else if( IsEquipmentPos( dst ) ) + { + msg = CanEquipItem( dstslot, eDest, pSrcItem, true ); + if( msg == EQUIP_ERR_OK ) + msg = CanUnequipItem( eDest, true ); + } - if( msg != EQUIP_ERR_OK ) + if( msg != EQUIP_ERR_OK ) + { + SendEquipError( msg, pSrcItem, pDstItem ); + return; + } + + // check dest->src move possibility + ItemPosCountVec sDest2; + uint16 eDest2; + if( IsInventoryPos( src ) ) + msg = CanStoreItem( srcbag, srcslot, sDest2, pDstItem, true ); + else if( IsBankPos( src ) ) + msg = CanBankItem( srcbag, srcslot, sDest2, pDstItem, true ); + else if( IsEquipmentPos( src ) ) + { + msg = CanEquipItem( srcslot, eDest2, pDstItem, true); + if( msg == EQUIP_ERR_OK ) + msg = CanUnequipItem( eDest2, true); + } + + if( msg != EQUIP_ERR_OK ) + { + SendEquipError( msg, pDstItem, pSrcItem ); + return; + } + + // Check bag swap with item exchange (one from empty in not bag possition (equipped (not possible in fact) or store) + if(pSrcItem->IsBag() && pDstItem->IsBag()) + { + Bag* emptyBag = NULL; + Bag* fullBag = NULL; + if(((Bag*)pSrcItem)->IsEmpty() && !IsBagPos(src)) { - SendEquipError( msg, pSrcItem, pDstItem ); - return; + emptyBag = (Bag*)pSrcItem; + fullBag = (Bag*)pDstItem; } - - // check dest->src move possibility - ItemPosCountVec sDest2; - uint16 eDest2; - if( IsInventoryPos( src ) ) - msg = CanStoreItem( srcbag, srcslot, sDest2, pDstItem, true ); - else if( IsBankPos( src ) ) - msg = CanBankItem( srcbag, srcslot, sDest2, pDstItem, true ); - else if( IsEquipmentPos( src ) ) + else if(((Bag*)pDstItem)->IsEmpty() && !IsBagPos(dst)) { - msg = CanEquipItem( srcslot, eDest2, pDstItem, true); - if( msg == EQUIP_ERR_OK ) - msg = CanUnequipItem( eDest2, true); + emptyBag = (Bag*)pDstItem; + fullBag = (Bag*)pSrcItem; } - if( msg != EQUIP_ERR_OK ) + // bag swap (with items exchange) case + if(emptyBag && fullBag) { - SendEquipError( msg, pDstItem, pSrcItem ); - return; - } + ItemPrototype const* emotyProto = emptyBag->GetProto(); - // now do moves, remove... - RemoveItem(dstbag, dstslot, false); - RemoveItem(srcbag, srcslot, false); + uint32 count = 0; - // add to dest - if( IsInventoryPos( dst ) ) - StoreItem(sDest, pSrcItem, true); - else if( IsBankPos( dst ) ) - BankItem(sDest, pSrcItem, true); - else if( IsEquipmentPos( dst ) ) - EquipItem(eDest, pSrcItem, true); - - // add to src - if( IsInventoryPos( src ) ) - StoreItem(sDest2, pDstItem, true); - else if( IsBankPos( src ) ) - BankItem(sDest2, pDstItem, true); - else if( IsEquipmentPos( src ) ) - EquipItem(eDest2, pDstItem, true); + for(int i=0; i < fullBag->GetBagSize(); ++i) + { + Item *bagItem = fullBag->GetItemByPos(i); + if (!bagItem) + continue; - AutoUnequipOffhandIfNeed(); + ItemPrototype const* bagItemProto = bagItem->GetProto(); + if (!bagItemProto || !ItemCanGoIntoBag(bagItemProto, emotyProto)) + { + // one from items not go to empry target bag + SendEquipError( EQUIP_ERR_NONEMPTY_BAG_OVER_OTHER_BAG, pSrcItem, pDstItem ); + return; + } + + ++count; + } + + + if (count > emptyBag->GetBagSize()) + { + // too small targeted bag + SendEquipError( EQUIP_ERR_ITEMS_CANT_BE_SWAPPED, pSrcItem, pDstItem ); + return; + } + + // Items swap + count = 0; // will pos in new bag + for(int i=0; i< fullBag->GetBagSize(); ++i) + { + Item *bagItem = fullBag->GetItemByPos(i); + if (!bagItem) + continue; + + fullBag->RemoveItem(i, true); + emptyBag->StoreItem(count, bagItem, true); + bagItem->SetState(ITEM_CHANGED, this); + + ++count; + } + } } + + // now do moves, remove... + RemoveItem(dstbag, dstslot, false); + RemoveItem(srcbag, srcslot, false); + + // add to dest + if( IsInventoryPos( dst ) ) + StoreItem(sDest, pSrcItem, true); + else if( IsBankPos( dst ) ) + BankItem(sDest, pSrcItem, true); + else if( IsEquipmentPos( dst ) ) + EquipItem(eDest, pSrcItem, true); + + // add to src + if( IsInventoryPos( src ) ) + StoreItem(sDest2, pDstItem, true); + else if( IsBankPos( src ) ) + BankItem(sDest2, pDstItem, true); + else if( IsEquipmentPos( src ) ) + EquipItem(eDest2, pDstItem, true); + + AutoUnequipOffhandIfNeed(); } void Player::AddItemToBuyBackSlot( Item *pItem ) @@ -11865,6 +12384,40 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a ((Player*)this)->ApplyRatingMod(CR_EXPERTISE, enchant_amount, apply); sLog.outDebug("+ %u EXPERTISE", enchant_amount); break; + case ITEM_MOD_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(enchant_amount), apply); + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + sLog.outDebug("+ %u ATTACK_POWER", enchant_amount); + break; + case ITEM_MOD_RANGED_ATTACK_POWER: + HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(enchant_amount), apply); + sLog.outDebug("+ %u RANGED_ATTACK_POWER", enchant_amount); + break; + case ITEM_MOD_FERAL_ATTACK_POWER: + ((Player*)this)->ApplyFeralAPBonus(enchant_amount, apply); + sLog.outDebug("+ %u FERAL_ATTACK_POWER", enchant_amount); + break; + case ITEM_MOD_SPELL_HEALING_DONE: + ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply); + sLog.outDebug("+ %u SPELL_HEALING_DONE", enchant_amount); + break; + case ITEM_MOD_SPELL_DAMAGE_DONE: + ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply); + sLog.outDebug("+ %u SPELL_DAMAGE_DONE", enchant_amount); + break; + case ITEM_MOD_MANA_REGENERATION: + ((Player*)this)->ApplyManaRegenBonus(enchant_amount, apply); + sLog.outDebug("+ %u MANA_REGENERATION", enchant_amount); + break; + case ITEM_MOD_ARMOR_PENETRATION_RATING: + ((Player*)this)->ApplyRatingMod(CR_ARMOR_PENETRATION, enchant_amount, apply); + sLog.outDebug("+ %u ARMOR PENETRATION", enchant_amount); + break; + case ITEM_MOD_SPELL_POWER: + ((Player*)this)->ApplySpellHealingBonus(enchant_amount, apply); + ((Player*)this)->ApplySpellDamageBonus(enchant_amount, apply); + sLog.outDebug("+ %u SPELL_POWER", enchant_amount); + break; default: break; } @@ -11888,8 +12441,14 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a } break; } + case ITEM_ENCHANTMENT_TYPE_USE_SPELL: + // processed in Player::CastItemUseSpell + break; + case ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET: + // nothing do.. + break; default: - sLog.outError("Unknown item enchantment display type: %d",enchant_display_type); + sLog.outError("Unknown item enchantment (id = %d) display type: %d", enchant_id, enchant_display_type); break; } /*switch(enchant_display_type)*/ } /*for*/ @@ -12363,8 +12922,6 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver ) // if not exist then created with set uState==NEW and rewarded=false QuestStatusData& questStatusData = mQuestStatus[quest_id]; - if (questStatusData.uState != QUEST_NEW) - questStatusData.uState = QUEST_CHANGED; // check for repeatable quests status reset questStatusData.m_status = QUEST_STATUS_INCOMPLETE; @@ -12372,18 +12929,18 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver ) if ( pQuest->HasFlag( QUEST_TRINITY_FLAGS_DELIVER ) ) { - for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + for(int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) questStatusData.m_itemcount[i] = 0; } if ( pQuest->HasFlag(QUEST_TRINITY_FLAGS_KILL_OR_CAST | QUEST_TRINITY_FLAGS_SPEAKTO) ) { - for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + for(int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) questStatusData.m_creatureOrGOcount[i] = 0; } GiveQuestSourceItem( pQuest ); - AdjustQuestReqItemCount( pQuest ); + AdjustQuestReqItemCount( pQuest, questStatusData ); if( pQuest->GetRepObjectiveFaction() ) SetFactionVisibleForFactionId(pQuest->GetRepObjectiveFaction()); @@ -12406,6 +12963,9 @@ void Player::AddQuest( Quest const *pQuest, Object *questGiver ) SetQuestSlot(log_slot, quest_id, qtime); + if (questStatusData.uState != QUEST_NEW) + questStatusData.uState = QUEST_CHANGED; + //starting initial quest script if(questGiver && pQuest->GetQuestStartScript()!=0) sWorld.ScriptsStart(sQuestStartScripts, pQuest->GetQuestStartScript(), questGiver, this); @@ -12523,6 +13083,12 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver SetTitle(titleEntry); } + if(pQuest->GetBonusTalents()) + { + m_questRewardTalentCount+=pQuest->GetBonusTalents(); + InitTalentForLevel(); + } + // Send reward mail if(pQuest->GetRewMailTemplateId()) { @@ -12554,12 +13120,13 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver Loot questMailLoot; - questMailLoot.FillLoot(pQuest->GetQuestId(), LootTemplates_QuestMail, this); + questMailLoot.FillLoot(pQuest->GetQuestId(), LootTemplates_QuestMail, this,true); // fill mail MailItemsInfo mi; // item list preparing - for(size_t i = 0; mi.size() < MAX_MAIL_ITEMS && i < questMailLoot.items.size(); ++i) + uint32 max_slot = questMailLoot.GetMaxSlotInLootFor(this); + for(uint32 i = 0; mi.size() < MAX_MAIL_ITEMS && i < max_slot; ++i) { if(LootItem* lootitem = questMailLoot.LootItemInSlot(i,this)) { @@ -12571,23 +13138,14 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver } } - for(size_t i = 0; mi.size() < MAX_MAIL_ITEMS && i < questMailLoot.quest_items.size(); ++i) - { - if(LootItem* lootitem = questMailLoot.LootItemInSlot(i+questMailLoot.items.size(),this)) - { - if(Item* item = Item::CreateItem(lootitem->itemid,lootitem->count,this)) - { - item->SaveToDB(); // save for prevent lost at next mail load, if send fail then item will deleted - mi.AddItem(item->GetGUIDLow(), item->GetEntry(), item); - } - } - } - WorldSession::SendMailTo(this, mailType, MAIL_STATIONERY_NORMAL, senderGuidOrEntry, GetGUIDLow(), "", 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE,pQuest->GetRewMailDelaySecs(),pQuest->GetRewMailTemplateId()); } if(pQuest->IsDaily()) + { SetDailyQuestStatus(quest_id); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, 1); + } if ( !pQuest->IsRepeatable() ) SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE); @@ -12600,6 +13158,8 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver SendQuestReward( pQuest, XP, questGiver ); if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST); } void Player::FailQuest( uint32 quest_id ) @@ -12624,8 +13184,9 @@ void Player::FailTimedQuest( uint32 quest_id ) { QuestStatusData& q_status = mQuestStatus[quest_id]; - if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; q_status.m_timer = 0; + if (q_status.uState != QUEST_NEW) + q_status.uState = QUEST_CHANGED; IncompleteQuest( quest_id ); @@ -13111,18 +13672,18 @@ uint32 Player::GetReqKillOrCastCurrentCount(uint32 quest_id, int32 entry) if( !qInfo ) return 0; - for (int j = 0; j < QUEST_OBJECTIVES_COUNT; j++) + for (int j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) if ( qInfo->ReqCreatureOrGOId[j] == entry ) return mQuestStatus[quest_id].m_creatureOrGOcount[j]; return 0; } -void Player::AdjustQuestReqItemCount( Quest const* pQuest ) +void Player::AdjustQuestReqItemCount( Quest const* pQuest, QuestStatusData& questStatusData ) { if ( pQuest->HasFlag( QUEST_TRINITY_FLAGS_DELIVER ) ) { - for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) + for(int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) { uint32 reqitemcount = pQuest->ReqItemCount[i]; if( reqitemcount != 0 ) @@ -13130,9 +13691,8 @@ void Player::AdjustQuestReqItemCount( Quest const* pQuest ) uint32 quest_id = pQuest->GetQuestId(); uint32 curitemcount = GetItemCount(pQuest->ReqItemId[i],true); - QuestStatusData& q_status = mQuestStatus[quest_id]; - q_status.m_itemcount[i] = std::min(curitemcount, reqitemcount); - if (q_status.uState != QUEST_NEW) q_status.uState = QUEST_CHANGED; + questStatusData.m_itemcount[i] = std::min(curitemcount, reqitemcount); + if (questStatusData.uState != QUEST_NEW) questStatusData.uState = QUEST_CHANGED; } } } @@ -13225,6 +13785,7 @@ void Player::ItemAddedQuestCheck( uint32 entry, uint32 count ) } } UpdateForQuestsGO(); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, entry); } void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count ) @@ -13271,6 +13832,7 @@ void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count ) void Player::KilledMonster( uint32 entry, uint64 guid ) { uint32 addkillcount = 1; + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, entry, addkillcount); for( int i = 0; i < MAX_QUEST_LOG_SIZE; i++ ) { uint32 questid = GetQuestSlotQuestId(i); @@ -13549,13 +14111,12 @@ void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGive uint32 questid = pQuest->GetQuestId(); sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", questid ); gameeventmgr.HandleQuestComplete(questid); - WorldPacket data( SMSG_QUESTGIVER_QUEST_COMPLETE, (4+4+4+4+4+4+pQuest->GetRewItemsCount()*8) ); - data << questid; - data << uint32(0x03); + WorldPacket data( SMSG_QUESTGIVER_QUEST_COMPLETE, (4+4+4+4+4) ); + data << uint32(questid); if ( getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL) ) { - data << XP; + data << uint32(XP); data << uint32(pQuest->GetRewOrReqMoney()); } else @@ -13563,16 +14124,9 @@ void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGive data << uint32(0); data << uint32(pQuest->GetRewOrReqMoney() + int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY))); } - data << uint32(0); // new 2.3.0, HonorPoints? - data << uint32( pQuest->GetRewItemsCount() ); // max is 5 - for (uint32 i = 0; i < pQuest->GetRewItemsCount(); ++i) - { - if ( pQuest->RewItemId[i] > 0 ) - data << pQuest->RewItemId[i] << pQuest->RewItemCount[i]; - else - data << uint32(0) << uint32(0); - } + data << uint32(10*Trinity::Honor::hk_honor_at_level(getLevel(), pQuest->GetRewHonorableKills())); + data << uint32(pQuest->GetBonusTalents()); // bonus talents GetSession()->SendPacket( &data ); if (pQuest->GetQuestCompleteScript() != 0) @@ -13583,8 +14137,9 @@ void Player::SendQuestFailed( uint32 quest_id ) { if( quest_id ) { - WorldPacket data( SMSG_QUESTGIVER_QUEST_FAILED, 4 ); + WorldPacket data( SMSG_QUESTGIVER_QUEST_FAILED, 4+4 ); data << quest_id; + data << uint32(0); // failed reason (4 for inventory is full) GetSession()->SendPacket( &data ); sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_FAILED"); } @@ -13623,10 +14178,10 @@ void Player::SendPushToPartyResponse( Player *pPlayer, uint32 msg ) void Player::SendQuestUpdateAddItem( Quest const* pQuest, uint32 item_idx, uint32 count ) { - WorldPacket data( SMSG_QUESTUPDATE_ADD_ITEM, (4+4) ); + WorldPacket data( SMSG_QUESTUPDATE_ADD_ITEM, 0 ); sLog.outDebug( "WORLD: Sent SMSG_QUESTUPDATE_ADD_ITEM" ); - data << pQuest->ReqItemId[item_idx]; - data << count; + //data << pQuest->ReqItemId[item_idx]; + //data << count; GetSession()->SendPacket( &data ); } @@ -13672,7 +14227,7 @@ bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid ) if(!LoadValues( fields[1].GetString())) { - sLog.outError("ERROR: Player #%d have broken data in `data` field. Can't be loaded.",GUID_LOPART(guid)); + sLog.outError("ERROR: Player #%d have broken data in `data` field. Can't be loaded for character list.",GUID_LOPART(guid)); if(delete_result) delete result; return false; } @@ -13742,7 +14297,7 @@ void Player::_LoadArenaTeamInfo(QueryResult *result) ArenaTeam* aTeam = objmgr.GetArenaTeamById(arenateamid); if(!aTeam) { - sLog.outError("FATAL: couldn't load arenateam %u", arenateamid); + sLog.outError("Player::_LoadArenaTeamInfo: couldn't load arenateam %u, week %u, season %u, rating %u", arenateamid, played_week, played_season, personal_rating); continue; } uint8 arenaSlot = aTeam->GetSlot(); @@ -13860,8 +14415,8 @@ float Player::GetFloatValueFromDB(uint16 index, uint64 guid) bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) { - //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [28] [29] 30 31 32 33 - //QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points FROM characters WHERE guid = '%u'", guid); + //// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [28] [29] 30 31 32 33 34 35 36 37 38 39 40 + //QueryResult *result = CharacterDatabase.PQuery("SELECT guid, account, data, name, race, class, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points,bgid,bgteam,bgmap,bgx,bgy,bgz,bgo FROM characters WHERE guid = '%u'", guid); QueryResult *result = holder->GetResult(PLAYER_LOGIN_QUERY_LOADFROM); if(!result) @@ -13930,22 +14485,19 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) //Other way is to saves m_team into characters table. setFactionForRace(m_race); SetCharm(0); + SetMover(this); m_class = fields[5].GetUInt8(); - PlayerInfo const *info = objmgr.GetPlayerInfo(m_race, m_class); - if(!info) - { - sLog.outError("Player have incorrect race/class pair. Can't be loaded."); - delete result; + // load home bind and check in same time class/race pair, it used later for restore broken positions + if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND))) return false; - } InitPrimaryProffesions(); // to max set before any spell loaded + // init saved position, and fix it later if problematic uint32 transGUID = fields[24].GetUInt32(); Relocate(fields[6].GetFloat(),fields[7].GetFloat(),fields[8].GetFloat(),fields[10].GetFloat()); - SetFallInformation(0, fields[8].GetFloat()); SetMapId(fields[9].GetUInt32()); SetDifficulty(fields[32].GetUInt32()); // may be changed in _LoadGroup @@ -13980,9 +14532,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) if(!IsPositionValid()) { sLog.outError("ERROR: Player (guidlow %d) have invalid coordinates (X: %f Y: %f Z: %f O: %f). Teleport to default race/class locations.",guid,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); - - SetMapId(info->mapId); - Relocate(info->positionX,info->positionY,info->positionZ,0.0f); + RelocateToHomebind(); transGUID = 0; @@ -13992,10 +14542,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) m_movementInfo.t_o = 0.0f; } - if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND))) - return false; - - // load the player's map here if it's not already loaded + /*// load the player's map here if it's not already loaded Map *map = GetMap(); if (!map) { @@ -14029,12 +14576,55 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) assert(false); } } + }*/ + + uint32 bgid = fields[34].GetUInt32(); + uint32 bgteam = fields[35].GetUInt32(); + + if(bgid) //saved in BattleGround + { + SetBattleGroundEntryPoint(fields[36].GetUInt32(),fields[37].GetFloat(),fields[38].GetFloat(),fields[39].GetFloat(),fields[40].GetFloat()); + + // check entry point and fix to homebind if need + MapEntry const* mapEntry = sMapStore.LookupEntry(m_bgEntryPoint.mapid); + if(!mapEntry || mapEntry->Instanceable() || !MapManager::IsValidMapCoord(m_bgEntryPoint)) + SetBattleGroundEntryPoint(m_homebindMapId,m_homebindX,m_homebindY,m_homebindZ,0.0f); + + BattleGround *currentBg = sBattleGroundMgr.GetBattleGround(bgid); + + if(currentBg && currentBg->IsPlayerInBattleGround(GetGUID())) + { + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(currentBg->GetTypeID(), currentBg->GetArenaType()); + uint32 queueSlot = AddBattleGroundQueueId(bgQueueTypeId); + + SetBattleGroundId(currentBg->GetInstanceID()); + SetBGTeam(bgteam); + + SetInviteForBattleGroundQueueType(bgQueueTypeId,currentBg->GetInstanceID()); + } + else + { + Relocate(GetBattleGroundEntryPoint()); + //RemoveArenaAuras(true); + } } - // since the player may not be bound to the map yet, make sure subsequent - // getmap calls won't create new maps - SetInstanceId(map->GetInstanceId()); + else + { + MapEntry const* mapEntry = sMapStore.LookupEntry(GetMapId()); + // if server restart after player save in BG or area + // player can have current coordinates in to BG/Arean map, fix this + if(!mapEntry || mapEntry->IsBattleGroundOrArena()) + { + // return to BG master + SetMapId(fields[36].GetUInt32()); + Relocate(fields[37].GetFloat(),fields[38].GetFloat(),fields[39].GetFloat(),fields[40].GetFloat()); - SaveRecallPosition(); + // check entry point and fix to homebind if need + mapEntry = sMapStore.LookupEntry(GetMapId()); + if(!mapEntry || mapEntry->IsBattleGroundOrArena() || !IsPositionValid()) + RelocateToHomebind(); + } + } if (transGUID != 0) { @@ -14053,8 +14643,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) guid,GetPositionX()+m_movementInfo.t_x,GetPositionY()+m_movementInfo.t_y, GetPositionZ()+m_movementInfo.t_z,GetOrientation()+m_movementInfo.t_o); - SetMapId(info->mapId); - Relocate(info->positionX,info->positionY,info->positionZ,0.0f); + RelocateToHomebind(); m_movementInfo.t_x = 0.0f; m_movementInfo.t_y = 0.0f; @@ -14083,8 +14672,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) sLog.outError("ERROR: Player (guidlow %d) have invalid transport guid (%u). Teleport to default race/class locations.", guid,transGUID); - SetMapId(info->mapId); - Relocate(info->positionX,info->positionY,info->positionZ,0.0f); + RelocateToHomebind(); m_movementInfo.t_x = 0.0f; m_movementInfo.t_y = 0.0f; @@ -14095,6 +14683,26 @@ 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()); + + // 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())) + { + AreaTrigger const* at = objmgr.GetMapEntranceTrigger(GetMapId()); + if(at) + Relocate(at->target_X, at->target_Y, at->target_Z, at->target_Orientation); + else + sLog.outError("Player %s(GUID: %u) logged in to a reset instance (map: %u) and there is no aretrigger leading to this map. Thus he can't be ported back to the entrance. This _might_ be an exploit attempt.", GetName(), GetGUIDLow(), GetMapId()); + } + + SaveRecallPosition(); + time_t now = time(NULL); time_t logoutTime = time_t(fields[16].GetUInt64()); @@ -14144,10 +14752,10 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) uint32 extraflags = fields[25].GetUInt32(); m_stableSlots = fields[26].GetUInt32(); - if(m_stableSlots > 2) + if(m_stableSlots > 4) { - sLog.outError("Player can have not more 2 stable slots, but have in DB %u",uint32(m_stableSlots)); - m_stableSlots = 2; + sLog.outError("Player can have not more 4 stable slots, but have in DB %u",uint32(m_stableSlots)); + m_stableSlots = 4; } m_atLoginFlags = fields[27].GetUInt32(); @@ -14171,34 +14779,18 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) // clear charm/summon related fields SetCharm(NULL); + SetMover(NULL); SetPet(NULL); - SetCharmerGUID(NULL); - SetOwnerGUID(NULL); - SetCreatorGUID(NULL); + SetCharmerGUID(0); + SetOwnerGUID(0); + SetCreatorGUID(0); // reset some aura modifiers before aura apply - SetFarSight(NULL); + SetFarSightGUID(0); SetUInt32Value(PLAYER_TRACK_CREATURES, 0 ); SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 ); - // reset skill modifiers and set correct unlearn flags - for (uint32 i = 0; i < PLAYER_MAX_SKILLS; i++) - { - SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0); - - // set correct unlearn bit - uint32 id = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; - if(!id) continue; - - SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(id); - if(!pSkill) continue; - - // enable unlearn button for primary professions only - if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) - SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,1)); - else - SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0)); - } + _LoadSkills(); // make sure the unit is considered out of combat for proper loading ClearInCombat(); @@ -14216,6 +14808,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) // reset stats before loading any modifiers InitStatsForLevel(); InitTaxiNodesForLevel(); + InitGlyphsForLevel(); + InitRunes(); // apply original stats mods before spell loading or item equipment that call before equip _RemoveStatsMods() @@ -14223,6 +14817,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) //_LoadMail(); _LoadAuras(holder->GetResult(PLAYER_LOGIN_QUERY_LOADAURAS), time_diff); + _LoadGlyphAuras(); // add ghost flag (must be after aura load: PLAYER_FLAGS_GHOST set in aura) if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) ) @@ -14230,14 +14825,14 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadSpells(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSPELLS)); - // after spell load - InitTalentForLevel(); - learnSkillRewardedSpells(); - // after spell load, learn rewarded spell if need also _LoadQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS)); _LoadDailyQuestStatus(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS)); + // after spell and quest load + InitTalentForLevel(); + learnDefaultSpells(); + _LoadTutorials(holder->GetResult(PLAYER_LOGIN_QUERY_LOADTUTORIALS)); // must be before inventory (some items required reputation check) @@ -14255,9 +14850,6 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) m_social = sSocialMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSOCIALLIST), GetGUIDLow()); - //if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND))) - // return false; - // check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES // note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded if(uint32 curTitle = GetUInt32Value(PLAYER_CHOSEN_TITLE)) @@ -14267,7 +14859,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) } // Not finish taxi flight path - if(!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes)) + if(!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes,GetTeam())) { // problems with taxi path loading TaxiNodesEntry const* nodeEntry = NULL; @@ -14277,8 +14869,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) if(!nodeEntry) // don't know taxi start node, to homebind { sLog.outError("Character %u have wrong data in taxi destination list, teleport to homebind.",GetGUIDLow()); - SetMapId(m_homebindMapId); - Relocate( m_homebindX, m_homebindY, m_homebindZ,0.0f); + RelocateToHomebind(); SaveRecallPosition(); // save as recall also to prevent recall and fall from sky } else // have start node, to it @@ -14303,6 +14894,9 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) // flight will started later } + // has to be called after last Relocate() in Player::LoadFromDB + SetFallInformation(0, GetPositionZ()); + _LoadSpellCooldowns(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS)); // Spell code allow apply any auras to dead character in load time in aura/spell/item loading @@ -14336,6 +14930,28 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) break; } + switch(sWorld.getConfig(CONFIG_GM_VISIBLE_STATE)) + { + default: + case 0: SetGMVisible(false); break; // invisible + case 1: break; // visible + case 2: // save state + if(extraflags & PLAYER_EXTRA_GM_INVISIBLE) + SetGMVisible(false); + break; + } + + /*switch(sWorld.getConfig(CONFIG_GM_ACCEPT_TICKETS)) + { + default: + case 0: break; // disable + case 1: SetAcceptTicket(true); break; // enable + case 2: // save state + if(extraflags & PLAYER_EXTRA_GM_ACCEPT_TICKETS) + SetAcceptTicket(true); + break; + }*/ + switch(sWorld.getConfig(CONFIG_GM_CHAT)) { default: @@ -14361,6 +14977,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadDeclinedNames(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES)); + m_achievementMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS), holder->GetResult(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS)); + m_achievementMgr.CheckAllAchievementCriteria(); return true; } @@ -14414,10 +15032,6 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) for (int i = 0; i < TOTAL_AURAS; i++) m_modAuras[i].clear(); - // all aura related fields - for(int i = UNIT_FIELD_AURA; i <= UNIT_FIELD_AURASTATE; ++i) - SetUInt32Value(i, 0); - //QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow()); if(result) @@ -14463,7 +15077,7 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) remaincharges = spellproto->procCharges; } else - remaincharges = -1; + remaincharges = 0; //do not load single target auras (unless they were cast by the player) if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto)) @@ -14488,6 +15102,36 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true); } +void Player::_LoadGlyphAuras() +{ + for (uint8 i = 0; i <= MAX_GLYPH_SLOT_INDEX; ++i) + { + if (uint32 glyph = GetGlyph(i)) + { + if (GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph)) + { + if (GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(GetGlyphSlot(i))) + { + if(gp->TypeFlags == gs->TypeFlags) + { + CastSpell(this, gp->SpellId, true); + continue; + } + else + sLog.outError("Player %s has glyph with typeflags %u in slot with typeflags %u, removing.", m_name.c_str(), gp->TypeFlags, gs->TypeFlags); + } + else + sLog.outError("Player %s has not existing glyph slot entry %u on index %u", m_name.c_str(), GetGlyphSlot(i), i); + } + else + sLog.outError("Player %s has not existing glyph entry %u on index %u", m_name.c_str(), glyph, i); + + // On any error remove glyph + SetGlyph(i, 0); + } + } +} + void Player::LoadCorpse() { if( isAlive() ) @@ -14663,15 +15307,16 @@ void Player::_LoadInventory(QueryResult *result, uint32 timediff) // load mailed item which should receive current player void Player::_LoadMailedItems(Mail *mail) { - QueryResult* result = CharacterDatabase.PQuery("SELECT item_guid, item_template FROM mail_items WHERE mail_id='%u'", mail->messageID); + // data needs to be at first place for Item::LoadFromDB + QueryResult* result = CharacterDatabase.PQuery("SELECT data, item_guid, item_template FROM mail_items JOIN item_instance ON item_guid = guid WHERE mail_id='%u'", mail->messageID); if(!result) return; do { Field *fields = result->Fetch(); - uint32 item_guid_low = fields[0].GetUInt32(); - uint32 item_template = fields[1].GetUInt32(); + uint32 item_guid_low = fields[1].GetUInt32(); + uint32 item_template = fields[2].GetUInt32(); mail->AddItem(item_guid_low, item_template); @@ -14687,7 +15332,7 @@ void Player::_LoadMailedItems(Mail *mail) Item *item = NewItemOrBag(proto); - if(!item->LoadFromDB(item_guid_low, 0)) + if(!item->LoadFromDB(item_guid_low, 0, result)) { sLog.outError( "Player::_LoadMailedItems - Item in mail (%u) doesn't exist !!!! - item guid: %u, deleted from mail", mail->messageID, item_guid_low); CharacterDatabase.PExecute("DELETE FROM mail_items WHERE item_guid = '%u'", item_guid_low); @@ -14868,6 +15513,9 @@ void Player::_LoadQuestStatus(QueryResult *result) if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId())) SetTitle(titleEntry); } + + if(pQuest->GetBonusTalents()) + m_questRewardTalentCount+=pQuest->GetBonusTalents(); } sLog.outDebug("Quest status is {%u} for quest {%u} for player (GUID: %u)", questStatusData.m_status, quest_id, GetGUIDLow()); @@ -14983,11 +15631,7 @@ void Player::_LoadReputation(QueryResult *result) void Player::_LoadSpells(QueryResult *result) { - for (PlayerSpellMap::iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr) - delete itr->second; - m_spells.clear(); - - //QueryResult *result = CharacterDatabase.PQuery("SELECT spell,slot,active FROM character_spell WHERE guid = '%u'",GetGUIDLow()); + //QueryResult *result = CharacterDatabase.PQuery("SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'",GetGUIDLow()); if(result) { @@ -14995,7 +15639,7 @@ void Player::_LoadSpells(QueryResult *result) { Field *fields = result->Fetch(); - addSpell(fields[0].GetUInt16(), fields[2].GetBool(), false, true, fields[1].GetUInt16(), fields[3].GetBool()); + addSpell(fields[0].GetUInt16(), fields[1].GetBool(), false, false, fields[2].GetBool()); } while( result->NextRow() ); @@ -15144,29 +15788,29 @@ InstancePlayerBind* Player::BindToInstance(InstanceSave *save, bool permanent, b void Player::SendRaidInfo() { + uint32 counter = 0; + WorldPacket data(SMSG_RAID_INSTANCE_INFO, 4); - uint32 counter = 0, i; - for(i = 0; i < TOTAL_DIFFICULTIES; i++) - for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr) - if(itr->second.perm) counter++; + size_t p_counter = data.wpos(); + data << uint32(counter); // placeholder - data << counter; - for(i = 0; i < TOTAL_DIFFICULTIES; i++) + for(int i = 0; i < TOTAL_DIFFICULTIES; ++i) { for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end(); ++itr) { if(itr->second.perm) { InstanceSave *save = itr->second.save; - data << (save->GetMapId()); - data << (uint32)(save->GetResetTime() - time(NULL)); - data << save->GetInstanceId(); - data << uint32(counter); - counter--; + data << uint32(save->GetMapId()); + data << uint32(save->GetResetTime() - time(NULL)); + data << uint32(save->GetInstanceId()); + data << uint32(save->GetDifficulty()); + ++counter; } } } + data.put<uint32>(p_counter,counter); GetSession()->SendPacket(&data); } @@ -15252,6 +15896,13 @@ void Player::ConvertInstancesToGroup(Player *player, Group *group, uint64 player bool Player::_LoadHomeBind(QueryResult *result) { + PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(), getClass()); + if(!info) + { + sLog.outError("Player have incorrect race/class pair. Can't be loaded."); + return false; + } + bool ok = false; //QueryResult *result = CharacterDatabase.PQuery("SELECT map,zone,position_x,position_y,position_z FROM character_homebind WHERE guid = '%u'", GUID_LOPART(playerGuid)); if (result) @@ -15276,9 +15927,6 @@ bool Player::_LoadHomeBind(QueryResult *result) if(!ok) { - PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(), getClass()); - if(!info) return false; - m_homebindMapId = info->mapId; m_homebindZoneId = info->zoneId; m_homebindX = info->positionX; @@ -15306,12 +15954,6 @@ void Player::SaveToDB() // first save/honor gain after midnight will also update the player's honor fields UpdateHonorFields(); - // players aren't saved on battleground maps - uint32 mapid = IsBeingTeleported() ? GetTeleportDest().mapid : GetMapId(); - const MapEntry * me = sMapStore.LookupEntry(mapid); - if(!me || me->IsBattleGroundOrArena()) - return; - int is_save_resting = HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0; //save, far from tavern/city //save, but in tavern/city @@ -15326,10 +15968,10 @@ void Player::SaveToDB() uint32 tmp_displayid = GetDisplayId(); // Set player sit state to standing on save, also stealth and shifted form - SetByteValue(UNIT_FIELD_BYTES_1, 0, 0); // stand state + SetStandState(UNIT_STAND_STATE_STAND); // stand state + RemoveStandFlags(UNIT_STAND_FLAGS_ALL); // stand flags? SetByteValue(UNIT_FIELD_BYTES_2, 3, 0); // shapeshift - SetByteValue(UNIT_FIELD_BYTES_1, 3, 0); // stand flags? - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); SetDisplayId(GetNativeDisplayId()); bool inworld = IsInWorld(); @@ -15347,23 +15989,14 @@ void Player::SaveToDB() "taximask, online, cinematic, " "totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, " "trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, " - "death_expire_time, taxi_path, arena_pending_points, latency) VALUES (" + "death_expire_time, taxi_path, arena_pending_points, latency, bgid, bgteam, bgmap, bgx, bgy, bgz, bgo) VALUES (" << GetGUIDLow() << ", " << GetSession()->GetAccountId() << ", '" << sql_name << "', " << m_race << ", " << m_class << ", "; - bool save_to_dest = false; - if(IsBeingTeleported()) - { - // don't save to battlegrounds or arenas - const MapEntry *entry = sMapStore.LookupEntry(GetTeleportDest().mapid); - if(entry && entry->map_type != MAP_BATTLEGROUND && entry->map_type != MAP_ARENA) - save_to_dest = true; - } - - if(!save_to_dest) + if(!IsBeingTeleported()) { ss << GetMapId() << ", " << (uint32)GetDifficulty() << ", " @@ -15388,12 +16021,11 @@ void Player::SaveToDB() ss << GetUInt32Value(i) << " "; } - ss << "', '"; + ss << "', "; - for( i = 0; i < 8; i++ ) - ss << m_taxi.GetTaximask(i) << " "; + ss << m_taxi; // string with TaxiMaskSize numbers - ss << "', "; + ss << ", "; ss << (inworld ? 1 : 0); ss << ", "; @@ -15447,9 +16079,19 @@ void Player::SaveToDB() ss << ", '"; ss << m_taxi.SaveTaxiDestinationsToString(); - ss << "', '0', '"; + ss << "', '0', "; ss << GetSession()->GetLatency(); - ss << "' )"; + ss << ", "; + ss << GetBattleGroundId(); + ss << ", "; + ss << GetBGTeam(); + ss << ", "; + ss << m_bgEntryPoint.mapid << ", " + << finiteAlways(m_bgEntryPoint.x) << ", " + << finiteAlways(m_bgEntryPoint.y) << ", " + << finiteAlways(m_bgEntryPoint.z) << ", " + << finiteAlways(m_bgEntryPoint.o); + ss << ")"; CharacterDatabase.Execute( ss.str().c_str() ); @@ -15480,7 +16122,7 @@ void Player::SaveToDB() pet->SavePetToDB(PET_SAVE_AS_CURRENT); //to prevent access to DB we should cache some data, which is used very often - CachePlayerInfoMap::iterator _iter = objmgr.m_mPlayerInfoMap.find(GetGUIDLow()); + /*CachePlayerInfoMap::iterator _iter = objmgr.m_mPlayerInfoMap.find(GetGUIDLow()); if(_iter != objmgr.m_mPlayerInfoMap.end())//skip new players { _iter->second->unLevel = getLevel(); @@ -15494,7 +16136,8 @@ void Player::SaveToDB() _iter->second->unArenaInfoId0 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (0 * 6)); _iter->second->unArenaInfoId1 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (1 * 6)); _iter->second->unArenaInfoId2 = GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (2 * 6)); - } + }*/ + m_achievementMgr.SaveToDB(); } // fast save function for item/money cheating preventing - save only inventory and money state @@ -15572,7 +16215,7 @@ void Player::_SaveAuras() { CharacterDatabase.PExecute("INSERT INTO character_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) " "VALUES ('%u', '" I64FMTD "' ,'%u', '%u', '%u', '%d', '%d', '%d', '%d')", - GetGUIDLow(), itr2->second->GetCasterGUID(), (uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), (uint32)itr2->second->GetStackAmount(), itr2->second->GetModifier()->m_amount,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->m_procCharges)); + GetGUIDLow(), itr2->second->GetCasterGUID(), (uint32)itr2->second->GetId(), (uint32)itr2->second->GetEffIndex(), (uint32)itr2->second->GetStackAmount(), itr2->second->GetModifier()->m_amount ,int(itr2->second->GetAuraMaxDuration()),int(itr2->second->GetAuraDuration()),int(itr2->second->GetAuraCharges())); } } } @@ -15773,18 +16416,26 @@ void Player::_SaveReputation() void Player::_SaveSpells() { - for (PlayerSpellMap::const_iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end(); itr = next) + for (PlayerSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end();) { - ++next; if (itr->second->state == PLAYERSPELL_REMOVED || itr->second->state == PLAYERSPELL_CHANGED) CharacterDatabase.PExecute("DELETE FROM character_spell WHERE guid = '%u' and spell = '%u'", GetGUIDLow(), itr->first); - if (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED) - CharacterDatabase.PExecute("INSERT INTO character_spell (guid,spell,slot,active,disabled) VALUES ('%u', '%u', '%u','%u','%u')", GetGUIDLow(), itr->first, itr->second->slotId,itr->second->active ? 1 : 0,itr->second->disabled ? 1 : 0); + + // add only changed/new not dependent spells + if (!itr->second->dependent && (itr->second->state == PLAYERSPELL_NEW || itr->second->state == PLAYERSPELL_CHANGED)) + CharacterDatabase.PExecute("INSERT INTO character_spell (guid,spell,active,disabled) VALUES ('%u', '%u', '%u', '%u')", GetGUIDLow(), itr->first, itr->second->active ? 1 : 0,itr->second->disabled ? 1 : 0); if (itr->second->state == PLAYERSPELL_REMOVED) - _removeSpell(itr->first); + { + delete itr->second; + m_spells.erase(itr++); + } else + { itr->second->state = PLAYERSPELL_UNCHANGED; + ++itr; + } + } } @@ -15956,6 +16607,42 @@ void Player::SetFloatValueInDB(uint16 index, float value, uint64 guid) Player::SetUInt32ValueInDB(index, temp, guid); } +void Player::Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair) +{ + Tokens tokens; + if(!LoadValuesArrayFromDB(tokens, guid)) + return; + + uint32 unit_bytes0 = GetUInt32ValueFromArray(tokens, UNIT_FIELD_BYTES_0); + uint8 race = unit_bytes0 & 0xFF; + uint8 class_ = (unit_bytes0 >> 8) & 0xFF; + + PlayerInfo const* info = objmgr.GetPlayerInfo(race, class_); + if(!info) + return; + + unit_bytes0 &= ~(0xFF << 16); + unit_bytes0 |= (gender << 16); + SetUInt32ValueInArray(tokens, UNIT_FIELD_BYTES_0, unit_bytes0); + + SetUInt32ValueInArray(tokens, UNIT_FIELD_DISPLAYID, gender ? info->displayId_f : info->displayId_m); + SetUInt32ValueInArray(tokens, UNIT_FIELD_NATIVEDISPLAYID, gender ? info->displayId_f : info->displayId_m); + + SetUInt32ValueInArray(tokens, PLAYER_BYTES, (skin | (face << 8) | (hairStyle << 16) | (hairColor << 24))); + + uint32 player_bytes2 = GetUInt32ValueFromArray(tokens, PLAYER_BYTES_2); + player_bytes2 &= ~0xFF; + player_bytes2 |= facialHair; + SetUInt32ValueInArray(tokens, PLAYER_BYTES_2, player_bytes2); + + uint32 player_bytes3 = GetUInt32ValueFromArray(tokens, PLAYER_BYTES_3); + player_bytes3 &= ~0xFF; + player_bytes3 |= gender; + SetUInt32ValueInArray(tokens, PLAYER_BYTES_3, player_bytes3); + + SaveValuesArrayInDB(tokens, guid); +} + void Player::SendAttackSwingNotStanding() { WorldPacket data(SMSG_ATTACKSWING_NOTSTANDING, 0); @@ -15988,7 +16675,8 @@ void Player::SendAttackSwingBadFacingAttack() void Player::SendAutoRepeatCancel() { - WorldPacket data(SMSG_CANCEL_AUTO_REPEAT, 0); + WorldPacket data(SMSG_CANCEL_AUTO_REPEAT, GetPackGUID().size()); + data.append(GetPackGUID()); // may be it's target guid GetSession()->SendPacket( &data ); } @@ -16217,6 +16905,7 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) { WorldPacket data(SMSG_PET_SPELLS, 8); data << uint64(0); + data << uint32(0); GetSession()->SendPacket(&data); if(GetGroup()) @@ -16348,65 +17037,79 @@ void Player::PetSpellInitialize() { Pet* pet = GetPet(); - if(pet) - { - uint8 addlist = 0; + if(!pet) + return; - sLog.outDebug("Pet Spells Groups"); + sLog.outDebug("Pet Spells Groups"); - CreatureInfo const *cinfo = pet->GetCreatureInfo(); + CharmInfo *charmInfo = pet->GetCharmInfo(); - if(pet->isControlled() && (pet->getPetType() == HUNTER_PET || cinfo && cinfo->type == CREATURE_TYPE_DEMON && getClass() == CLASS_WARLOCK)) - { - for(PetSpellMap::iterator itr = pet->m_spells.begin();itr != pet->m_spells.end();++itr) - { - if(itr->second->state == PETSPELL_REMOVED) - continue; - ++addlist; - } - } + WorldPacket data(SMSG_PET_SPELLS, 8+4+4+4+10*4); + data << uint64(pet->GetGUID()); + data << uint32(pet->GetCreatureInfo()->family); // creature family (required for pet talents) + data << uint32(0); + data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); - // first line + actionbar + spellcount + spells + last adds - WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25); + // action bar loop + for(uint32 i = 0; i < 10; i++) + { + data << uint32(charmInfo->GetActionBarEntry(i)->Raw); + } - CharmInfo *charmInfo = pet->GetCharmInfo(); + size_t spellsCountPos = data.wpos(); - //16 - data << (uint64)pet->GetGUID() << uint32(0x00000000) << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); + // spells count + uint8 addlist = 0; + data << uint8(addlist); // placeholder - for(uint32 i = 0; i < 10; i++) //40 + if(pet->isControlled() && ((pet->getPetType() == HUNTER_PET) || ((pet->GetCreatureInfo()->type == CREATURE_TYPE_DEMON) && (getClass() == CLASS_WARLOCK)))) + { + // spells loop + for (PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr) { - data << uint16(charmInfo->GetActionBarEntry(i)->SpellOrAction) << uint16(charmInfo->GetActionBarEntry(i)->Type); + if(itr->second->state == PETSPELL_REMOVED) + continue; + + data << uint16(itr->first); + data << uint16(itr->second->active); // pet spell active state isn't boolean + ++addlist; } + } - data << uint8(addlist); //1 + data.put<uint8>(spellsCountPos, addlist); - if(addlist && pet->isControlled()) - { - for (PetSpellMap::iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr) - { - if(itr->second->state == PETSPELL_REMOVED) - continue; + uint8 cooldownsCount = pet->m_CreatureSpellCooldowns.size() + pet->m_CreatureCategoryCooldowns.size(); + data << uint8(cooldownsCount); - data << uint16(itr->first); - data << uint16(itr->second->active); // pet spell active state isn't boolean - } - } + time_t curTime = time(NULL); - //data << uint8(0x01) << uint32(0x6010) << uint32(0x01) << uint32(0x05) << uint16(0x00); //15 - uint8 count = 3; //1+8+8+8=25 + for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureSpellCooldowns.begin(); itr != pet->m_CreatureSpellCooldowns.end(); ++itr) + { + time_t cooldown = 0; - // if count = 0, then end of packet... - data << count; - // uint32 value is spell id... - // uint64 value is constant 0, unknown... - data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 - //data << uint32(0x5fd1) << uint64(0); // if count = 2 - data << uint32(0x8e8c) << uint64(0); // if count = 3 - data << uint32(0x8e8b) << uint64(0); // if count = 3 + if(itr->second > curTime) + cooldown = (itr->second - curTime) * 1000; - GetSession()->SendPacket(&data); + data << uint16(itr->first); // spellid + data << uint16(0); // spell category? + data << uint32(itr->second); // cooldown + data << uint32(0); // category cooldown } + + for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureCategoryCooldowns.begin(); itr != pet->m_CreatureCategoryCooldowns.end(); ++itr) + { + time_t cooldown = 0; + + if(itr->second > curTime) + cooldown = (itr->second - curTime) * 1000; + + data << uint16(itr->first); // spellid + data << uint16(0); // spell category? + data << uint32(0); // cooldown + data << uint32(itr->second); // category cooldown + } + + GetSession()->SendPacket(&data); } void Player::PossessSpellInitialize() @@ -16428,7 +17131,10 @@ void Player::PossessSpellInitialize() WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);// first line + actionbar + spellcount + spells + last adds //16 - data << (uint64)charm->GetGUID() << uint32(0x00000000) << uint8(0) << uint8(0) << uint16(0); + data << uint64(charm->GetGUID()); + data << uint32(0x00000000); + data << uint32(0); + data << uint8(0) << uint8(0) << uint16(0); for(uint32 i = 0; i < 10; i++) //40 { @@ -16437,11 +17143,8 @@ void Player::PossessSpellInitialize() data << uint8(addlist); //1 - uint8 count = 3; - data << count; - data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 - data << uint32(0x8e8c) << uint64(0); // if count = 3 - data << uint32(0x8e8b) << uint64(0); // if count = 3 + uint8 count = 0; + data << uint8(count); // cooldowns count GetSession()->SendPacket(&data); } @@ -16478,13 +17181,13 @@ void Player::CharmSpellInitialize() WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25);// first line + actionbar + spellcount + spells + last adds - data << (uint64)charm->GetGUID() << uint32(0x00000000); - + data << uint64(charm->GetGUID()); + data << uint32(0x00000000); + data << uint32(0); if(charm->GetTypeId() != TYPEID_PLAYER) data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()); else data << uint8(0) << uint8(0); - data << uint16(0); for(uint32 i = 0; i < 10; i++) //40 @@ -16507,51 +17210,12 @@ void Player::CharmSpellInitialize() } } - uint8 count = 3; - data << count; - data << uint32(0x6010) << uint64(0); // if count = 1, 2 or 3 - data << uint32(0x8e8c) << uint64(0); // if count = 3 - data << uint32(0x8e8b) << uint64(0); // if count = 3 + uint8 count = 0; + data << uint8(count); // cooldowns count GetSession()->SendPacket(&data); } -int32 Player::GetTotalFlatMods(uint32 spellId, SpellModOp op) -{ - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); - if (!spellInfo) return 0; - int32 total = 0; - for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr) - { - SpellModifier *mod = *itr; - - if(!IsAffectedBySpellmod(spellInfo,mod)) - continue; - - if (mod->type == SPELLMOD_FLAT) - total += mod->value; - } - return total; -} - -int32 Player::GetTotalPctMods(uint32 spellId, SpellModOp op) -{ - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); - if (!spellInfo) return 0; - int32 total = 0; - for (SpellModList::iterator itr = m_spellMods[op].begin(); itr != m_spellMods[op].end(); ++itr) - { - SpellModifier *mod = *itr; - - if(!IsAffectedBySpellmod(spellInfo,mod)) - continue; - - if (mod->type == SPELLMOD_PCT) - total += mod->value; - } - return total; -} - bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell) { if (!mod || !spellInfo) @@ -16569,22 +17233,27 @@ bool Player::IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mo return false; } - return spellmgr.IsAffectedBySpell(spellInfo,mod->spellId,mod->effectId,mod->mask); + return spellmgr.IsAffectedByMod(spellInfo, mod); } void Player::AddSpellMod(SpellModifier* mod, bool apply) { uint16 Opcode= (mod->type == SPELLMOD_FLAT) ? SMSG_SET_FLAT_SPELL_MODIFIER : SMSG_SET_PCT_SPELL_MODIFIER; - for(int eff=0;eff<64;++eff) + uint8 i=0; + flag96 _mask; + for(int eff=0;eff<96;++eff) { - uint64 _mask = uint64(1) << eff; + if ((eff!=0) && (eff%32==0)) + i++; + + _mask[i] = uint32(1) << (eff-(32*i)); if ( mod->mask & _mask) { int32 val = 0; for (SpellModList::iterator itr = m_spellMods[mod->op].begin(); itr != m_spellMods[mod->op].end(); ++itr) { - if ((*itr)->type == mod->type && (*itr)->mask & _mask) + if ((*itr)->type == mod->type && (*itr)->mask & _mask ) val += (*itr)->value; } val += apply ? mod->value : -(mod->value); @@ -16683,6 +17352,27 @@ void Player::RemovePetitionsAndSigns(uint64 guid, uint32 type) CharacterDatabase.CommitTransaction(); } +void Player::LeaveAllArenaTeams(uint64 guid) +{ + QueryResult *result = CharacterDatabase.PQuery("SELECT arena_team_member.arenateamid FROM arena_team_member JOIN arena_team ON arena_team_member.arenateamid = arena_team.arenateamid WHERE guid='%u'", GUID_LOPART(guid)); + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + uint32 at_id = fields[0].GetUInt32(); + if(at_id != 0) + { + ArenaTeam * at = objmgr.GetArenaTeamById(at_id); + if(at) + at->DelMember(guid); + } + } while (result->NextRow()); + + delete result; +} + void Player::SetRestBonus (float rest_bonus_new) { // Prevent resting on max level @@ -16713,7 +17403,7 @@ void Player::HandleStealthedUnitsDetection() { std::list<Unit*> stealthedUnits; Trinity::AnyStealthedCheck u_check; - Trinity::UnitListSearcher<Trinity::AnyStealthedCheck > searcher(stealthedUnits, u_check); + Trinity::UnitListSearcher<Trinity::AnyStealthedCheck > searcher(this, stealthedUnits, u_check); VisitNearbyObject(World::GetMaxVisibleDistance(), searcher); for (std::list<Unit*>::iterator i = stealthedUnits.begin(); i != stealthedUnits.end(); ++i) @@ -16732,7 +17422,7 @@ void Player::HandleStealthedUnitsDetection() // send data at target visibility change (adding to client) if((*i)!=this && (*i)->isType(TYPEMASK_UNIT)) { - SendAuraDurationsForTarget(*i); + SendAurasForTarget(*i); //if(((Unit*)(*i))->isAlive()) //should be always alive { if((*i)->GetTypeId()==TYPEID_UNIT) @@ -17528,6 +18218,10 @@ bool Player::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList, bool if (u == this) return true; + // phased visibility (both must phased in same way) + if(!InSamePhase(u)) + return false; + // player visible for other player if not logout and at same transport // including case when player is out of world bool at_same_transport = @@ -17726,7 +18420,7 @@ void Player::UpdateVisibilityOf(WorldObject* target) // send data at target visibility change (adding to client) if(target!=this && target->isType(TYPEMASK_UNIT)) { - SendAuraDurationsForTarget((Unit*)target); + SendAurasForTarget((Unit*)target); if(((Unit*)target)->isAlive()) { if(target->GetTypeId()==TYPEID_UNIT) @@ -17905,7 +18599,7 @@ void Player::SetGroup(Group *group, int8 subgroup) void Player::SendInitialPacketsBeforeAddToMap() { - WorldPacket data(SMSG_SET_REST_START, 4); + WorldPacket data(SMSG_SET_REST_START_OBSOLETE, 4); data << uint32(0); // unknown, may be rest state time or experience GetSession()->SendPacket(&data); @@ -17933,6 +18627,7 @@ void Player::SendInitialPacketsBeforeAddToMap() SendInitialActionButtons(); SendInitialReputations(); + m_achievementMgr.SendAllAchievementData(); UpdateZone(GetZoneId()); SendInitWorldStates(); @@ -17943,13 +18638,23 @@ void Player::SendInitialPacketsBeforeAddToMap() data << (float)0.01666667f; // game speed GetSession()->SendPacket( &data ); + data.Initialize(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement + data << uint32(0x00000000); // on blizz it increments periodically + GetSession()->SendPacket(&data); + // set fly flag if in fly form or taxi flight to prevent visually drop at ground in showup moment if(HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED) || isInFlight()) AddUnitMovementFlag(MOVEMENTFLAG_FLYING2); + + m_mover = this; } void Player::SendInitialPacketsAfterAddToMap() { + WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement + data << uint32(0x00000000); // on blizz it increments periodically + GetSession()->SendPacket(&data); + CastSpell(this, 836, true); // LOGINEFFECT // set some aura effects that send packet to player client after add player to map @@ -17980,6 +18685,41 @@ void Player::SendInitialPacketsAfterAddToMap() SendMessageToSet(&data,true); } + // setup BG group membership if need + if(BattleGround* currentBg = GetBattleGround()) + { + // call for invited (join) or listed (relogin) and avoid other cases (GM teleport) + if (IsInvitedForBattleGroundInstance(GetBattleGroundId()) || + currentBg->IsPlayerInBattleGround(GetGUID())) + { + currentBg->PlayerRelogin(this); + if(currentBg->GetMapId() == GetMapId()) // we teleported/login to/in bg + { + uint32 team = currentBg->GetPlayerTeam(GetGUID()); + if(!team) + team = GetTeam(); + Group* group = currentBg->GetBgRaid(team); + if(!group) // first player joined + { + group = new Group; + currentBg->SetBgRaid(team, group); + group->Create(GetGUIDLow(), GetName()); + } + else // raid already exist + { + if(group->IsMember(GetGUID())) + { + uint8 subgroup = group->GetMemberGroup(GetGUID()); + SetGroup(group, subgroup); + } + else + currentBg->GetBgRaid(team)->AddMember(GetGUID(), GetName()); + } + } + } + } + + SendAurasForTarget(this); SendEnchantmentDurations(); // must be after add to map SendItemDurations(); // must be after add to map } @@ -17992,16 +18732,24 @@ void Player::SendUpdateToOutOfRangeGroupMembers() group->UpdatePlayerOutOfRange(this); m_groupUpdateMask = GROUP_UPDATE_FLAG_NONE; - m_auraUpdateMask = 0; + m_auraRaidUpdateMask = 0; if(Pet *pet = GetPet()) - pet->ResetAuraUpdateMask(); + pet->ResetAuraUpdateMaskForRaid(); } -void Player::SendTransferAborted(uint32 mapid, uint16 reason) +void Player::SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg) { WorldPacket data(SMSG_TRANSFER_ABORTED, 4+2); data << uint32(mapid); - data << uint16(reason); // transfer abort reason + data << uint8(reason); // transfer abort reason + switch(reason) + { + case TRANSFER_ABORT_INSUF_EXPAN_LVL: + case TRANSFER_ABORT_DIFFICULTY: + case TRANSFER_ABORT_UNIQUE_MESSAGE: + data << uint8(arg); + break; + } GetSession()->SendPacket(&data); } @@ -18067,22 +18815,18 @@ void Player::resetSpells() learnQuestRewardedSpells(); } -void Player::learnDefaultSpells(bool loading) +void Player::learnDefaultSpells() { // learn default race/class spells PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(),getClass()); - std::list<CreateSpellPair>::const_iterator spell_itr; - for (spell_itr = info->spell.begin(); spell_itr!=info->spell.end(); ++spell_itr) + for (PlayerCreateInfoSpells::const_iterator itr = info->spell.begin(); itr!=info->spell.end(); ++itr) { - uint16 tspell = spell_itr->first; - if (tspell) - { - sLog.outDebug("PLAYER: Adding initial spell, id = %u",tspell); - if(loading || !spell_itr->second) // not care about passive spells or loading case - addSpell(tspell,spell_itr->second); - else // but send in normal spell in game learn case - learnSpell(tspell); - } + uint32 tspell = *itr; + sLog.outDebug("PLAYER (Class: %u Race: %u): Adding initial spell, id = %u",uint32(getClass()),uint32(getRace()), tspell); + if(!IsInWorld()) // will send in INITIAL_SPELLS in list anyway at map add + addSpell(tspell,true,true,true,false); + else // but send in normal spell in game learn case + learnSpell(tspell,true); } } @@ -18174,7 +18918,7 @@ void Player::learnQuestRewardedSpells() } } -void Player::learnSkillRewardedSpells(uint32 skill_id ) +void Player::learnSkillRewardedSpells(uint32 skill_id, uint32 skill_value ) { uint32 raceMask = getRaceMask(); uint32 classMask = getClassMask(); @@ -18192,35 +18936,67 @@ void Player::learnSkillRewardedSpells(uint32 skill_id ) if (sSpellStore.LookupEntry(pAbility->spellId)) { - // Ok need learn spell - learnSpell(pAbility->spellId); + // need unlearn spell + if (skill_value < pAbility->req_skill_value) + removeSpell(pAbility->spellId); + // need learn + else if (!IsInWorld()) + addSpell(pAbility->spellId,true,true,true,false); + else + learnSpell(pAbility->spellId,true); } } } -void Player::learnSkillRewardedSpells() +void Player::SendAurasForTarget(Unit *target) { - for (uint16 i=0; i < PLAYER_MAX_SKILLS; i++) - { - if(!GetUInt32Value(PLAYER_SKILL_INDEX(i))) - continue; - - uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; + if(!target || target->GetVisibleAuras()->empty()) // speedup things + return; - learnSkillRewardedSpells(pskill); - } -} + WorldPacket data(SMSG_AURA_UPDATE_ALL); + data.append(target->GetPackGUID()); -void Player::SendAuraDurationsForTarget(Unit* target) -{ - for(Unit::AuraMap::const_iterator itr = target->GetAuras().begin(); itr != target->GetAuras().end(); ++itr) + Unit::VisibleAuraMap const *visibleAuras = target->GetVisibleAuras(); + for(Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); itr != visibleAuras->end(); ++itr) { - Aura* aura = itr->second; - if(aura->GetAuraSlot() >= MAX_AURAS || aura->IsPassive() || aura->GetCasterGUID()!=GetGUID()) - continue; + Aura * aura=NULL; + for (uint8 i=0 ; i<3; i++) + { + if (itr->second.m_slotAuras[i]) + { + aura=itr->second.m_slotAuras[i]; + break; + } + } + if(aura) + { + data << uint8(aura->GetAuraSlot()); + data << uint32(aura->GetId()); + + if(aura->GetId()) + { + // flags + data << itr->second.m_Flags; + // level + data << itr->second.m_Level; + // charges + data << uint8(aura->GetAuraCharges()); + + if(!(itr->second.m_Flags & AFLAG_NOT_CASTER)) + { + data << uint8(0); // packed GUID of someone (caster?) + } - aura->SendAuraDurationForCaster(this); + if(itr->second.m_Flags & AFLAG_DURATION) // include aura duration + { + data << uint32(aura->GetAuraMaxDuration()); + data << uint32(aura->GetAuraDuration()); + } + } + } } + + GetSession()->SendPacket(&data); } void Player::SetDailyQuestStatus( uint32 quest_id ) @@ -18264,7 +19040,7 @@ bool Player::InArena() const return true; } -bool Player::GetBGAccessByLevel(uint32 bgTypeId) const +bool Player::GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const { // get a template bg instead of running one BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); @@ -18282,15 +19058,15 @@ uint32 Player::GetMinLevelForBattleGroundQueueId(uint32 queue_id) if(queue_id < 1) return 0; - if(queue_id >=6) - queue_id = 6; + if(queue_id >=7) + queue_id = 7; return 10*(queue_id+1); } uint32 Player::GetMaxLevelForBattleGroundQueueId(uint32 queue_id) { - if(queue_id >=6) + if(queue_id >=7) return 255; // hardcoded max level return 10*(queue_id+2)-1; @@ -18302,8 +19078,8 @@ uint32 Player::GetBattleGroundQueueIdFromLevel() const uint32 level = getLevel(); if(level <= 19) return 0; - else if (level > 69) - return 6; + else if (level > 79) + return 7; else return level/10 - 1; // 20..29 -> 1, 30-39 -> 2, ... /* @@ -18333,18 +19109,23 @@ bool Player::IsSpellFitByClassAndRace( uint32 spell_id ) const SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spell_id); SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spell_id); + if(lower==upper) + return true; for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) { // skip wrong race skills if( _spell_idx->second->racemask && (_spell_idx->second->racemask & racemask) == 0) - return false; + continue; // skip wrong class skills if( _spell_idx->second->classmask && (_spell_idx->second->classmask & classmask) == 0) - return false; + continue; + + return true; } - return true; + + return false; } bool Player::HasQuestForGO(int32 GOId) @@ -18449,9 +19230,8 @@ void Player::AutoUnequipOffhandIfNeed() if(!offItem) return; - Item *mainItem = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND ); - - if(!mainItem || mainItem->GetProto()->InventoryType != INVTYPE_2HWEAPON) + // need unequip for 2h-weapon without TitanGrip + if (!IsTwoHandUsed()) return; ItemPosCountVec off_dest; @@ -18484,7 +19264,7 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons case ITEM_CLASS_WEAPON: { for(int i= EQUIPMENT_SLOT_MAINHAND; i < EQUIPMENT_SLOT_TABARD; ++i) - if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + if(Item *item = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, i )) if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) return true; break; @@ -18493,17 +19273,17 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons { // tabard not have dependent spells for(int i= EQUIPMENT_SLOT_START; i< EQUIPMENT_SLOT_MAINHAND; ++i) - if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, i )) + if(Item *item = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, i )) if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) return true; // shields can be equipped to offhand slot - if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) + if(Item *item = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND)) if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) return true; // ranged slot can have some armor subclasses - if(Item *item = GetItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED)) + if(Item *item = GetUseableItemByPos( INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED)) if(item!=ignoreItem && item->IsFitToSpellRequirements(spellInfo)) return true; @@ -18517,6 +19297,24 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons return false; } +bool Player::CanNoReagentCast(SpellEntry const* spellInfo) const +{ + // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP + if (spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP && + HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION)) + return true; + + // Check no reagent use mask + flag96 noReagentMask; + noReagentMask[0] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1); + noReagentMask[1] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1+1); + noReagentMask[2] = GetUInt32Value(PLAYER_NO_REAGENT_COST_1+2); + if (spellInfo->SpellFamilyFlags & noReagentMask) + return true; + + return false; +} + void Player::RemoveItemDependentAurasAndCasts( Item * pItem ) { AuraMap& auras = GetAuras(); @@ -18562,7 +19360,7 @@ uint32 Player::GetResurrectionSpellId() for(AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) { // Soulstone Resurrection // prio: 3 (max, non death persistent) - if( prio < 2 && (*itr)->GetSpellProto()->SpellVisual == 99 && (*itr)->GetSpellProto()->SpellIconID == 92 ) + if( prio < 2 && (*itr)->GetSpellProto()->SpellVisual[0] == 99 && (*itr)->GetSpellProto()->SpellIconID == 92 ) { switch((*itr)->GetId()) { @@ -18572,6 +19370,7 @@ uint32 Player::GetResurrectionSpellId() case 20764: spell_id = 20760; break; // rank 4 case 20765: spell_id = 20761; break; // rank 5 case 27239: spell_id = 27240; break; // rank 6 + case 47883: spell_id = 47882; break; // rank 7 default: sLog.outError("Unhandled spell %%u: S.Resurrection",(*itr)->GetId()); continue; @@ -18594,6 +19393,26 @@ uint32 Player::GetResurrectionSpellId() return spell_id; } +// Used in triggers for check "Only to targets that grant experience or honor" req +bool Player::isHonorOrXPTarget(Unit* pVictim) +{ + uint32 v_level = pVictim->getLevel(); + uint32 k_grey = Trinity::XP::GetGrayLevel(getLevel()); + + // Victim level less gray level + if(v_level<=k_grey) + return false; + + if(pVictim->GetTypeId() == TYPEID_UNIT) + { + if (((Creature*)pVictim)->isTotem() || + ((Creature*)pVictim)->isPet() || + ((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL) + return false; + } + return true; +} + bool Player::RewardPlayerAndGroupAtKill(Unit* pVictim) { bool PvP = pVictim->isCharmedOwnedByPlayerOrPlayer(); @@ -18721,6 +19540,9 @@ uint32 Player::GetBaseWeaponSkillValue (WeaponAttackType attType) const void Player::ResurectUsingRequestData() { + /// Teleport before resurrecting, otherwise the player might get attacked from creatures near his corpse + TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation()); + ResurrectPlayer(0.0f,false); if(GetMaxHealth() > m_resurrectHealth) @@ -18738,8 +19560,6 @@ void Player::ResurectUsingRequestData() SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY) ); SpawnCorpseBones(); - - TeleportTo(m_resurrectMap, m_resurrectX, m_resurrectY, m_resurrectZ, GetOrientation()); } void Player::SetClientControl(Unit* target, uint8 allowMove) @@ -18753,28 +19573,31 @@ void Player::SetClientControl(Unit* target, uint8 allowMove) void Player::UpdateZoneDependentAuras( uint32 newZone ) { // remove new continent flight forms - if( !isGameMaster() && - GetVirtualMapForMapAndZone(GetMapId(),newZone) != 530) + if( !IsAllowUseFlyMountsHere() ) { RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED); RemoveSpellsCausingAura(SPELL_AURA_FLY); } // Some spells applied at enter into zone (with subzones) - // Human Illusion - // NOTE: these are removed by RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP); - if ( newZone == 2367 ) // Old Hillsbrad Foothills - { - uint32 spellid = 0; - // all horde races - if( GetTeam() == HORDE ) - spellid = getGender() == GENDER_FEMALE ? 35481 : 35480; - // and some alliance races - else if( getRace() == RACE_NIGHTELF || getRace() == RACE_DRAENEI ) - spellid = getGender() == GENDER_FEMALE ? 35483 : 35482; - - if(spellid && !HasAura(spellid,0) ) - CastSpell(this,spellid,true); + switch(newZone) + { + case 2367: // Old Hillsbrad Foothills + { + // Human Illusion + // NOTE: these are removed by RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CHANGE_MAP); + uint32 spellid = 0; + // all horde races + if( GetTeam() == HORDE ) + spellid = getGender() == GENDER_FEMALE ? 35481 : 35480; + // and some alliance races + else if( getRace() == RACE_NIGHTELF || getRace() == RACE_DRAENEI ) + spellid = getGender() == GENDER_FEMALE ? 35483 : 35482; + + if(spellid && !HasAura(spellid,0) ) + CastSpell(this,spellid,true); + break; + } } } @@ -18784,25 +19607,41 @@ void Player::UpdateAreaDependentAuras( uint32 newArea ) for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) { // use m_zoneUpdateId for speed: UpdateArea called from UpdateZone or instead UpdateZone in both cases m_zoneUpdateId up-to-date - if(!IsSpellAllowedInLocation(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea)) + if(GetSpellAllowedInLocationError(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea,GetBattleGroundId())!=0) RemoveAura(iter); else ++iter; } - // unmount if enter in this subzone - if( newArea == 35) - RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); - // Dragonmaw Illusion - else if( newArea == 3759 || newArea == 3966 || newArea == 3939 ) + // some auras applied at subzone enter + switch(newArea) { - if( GetDummyAura(40214) ) - { - if( !HasAura(40216,0) ) - CastSpell(this,40216,true); - if( !HasAura(42016,0) ) - CastSpell(this,42016,true); - } + // Dragonmaw Illusion + case 3759: // Netherwing Ledge + case 3939: // Dragonmaw Fortress + case 3966: // Dragonmaw Base Camp + if( GetDummyAura(40214) ) + { + if( !HasAura(40216,0) ) + CastSpell(this,40216,true); + if( !HasAura(42016,0) ) + CastSpell(this,42016,true); + } + break; + // Dominion Over Acherus + case 4281: // Acherus: The Ebon Hold + case 4342: // Acherus: The Ebon Hold + if( HasSpell(51721) ) + if( !HasAura(51721,0) ) + CastSpell(this,51721,true); + break; + // Mist of the Kvaldir + case 4028: //Riplash Strand + case 4029: //Riplash Ruins + case 4106: //Garrosh's Landing + case 4031: //Pal'ea + CastSpell(this,54119,true); + break; } } @@ -18937,18 +19776,20 @@ PartyResult Player::CanUninviteFromGroup() const void Player::UpdateUnderwaterState( Map* m, float x, float y, float z ) { float water_z = m->GetWaterLevel(x,y); - float height_z = m->GetHeight(x,y,z, false); // use .map base surface height + float terrain_z = m->GetHeight(x,y,z, false); // use .map base surface height uint8 flag1 = m->GetTerrainType(x,y); - //!Underwater check, not in water if underground or above water level - if (height_z <= INVALID_HEIGHT || z < (height_z-2) || z > (water_z - 2) ) - m_isunderwater &= 0x7A; + //!Underwater check, not in water if underground or above water level - take UC royal quater for example + if (terrain_z <= INVALID_HEIGHT || z < (terrain_z-2) || z > (water_z - 2) ) + m_isunderwater &= ~UNDERWATER_INWATER; else if ((z < (water_z - 2)) && (flag1 & 0x01)) - m_isunderwater |= 0x01; + m_isunderwater |= UNDERWATER_INWATER; //!in lava check, anywhere under lava level - if ((height_z <= INVALID_HEIGHT || z < (height_z - 0)) && (flag1 == 0x00) && IsInWater()) - m_isunderwater |= 0x80; + if ((terrain_z <= INVALID_HEIGHT || z < (terrain_z - 0)) && (flag1 == 0x00) && IsInWater()) + m_isunderwater |= UNDERWATER_INLAVA; + else + m_isunderwater &= ~UNDERWATER_INLAVA; } void Player::SetCanParry( bool value ) @@ -18983,8 +19824,8 @@ bool ItemPosCount::isContainedIn(ItemPosCountVec const& vec) const void Player::HandleFallDamage(MovementInfo& movementInfo) { - if(movementInfo.fallTime < 1500) - return; + //if(movementInfo.fallTime < 1500) + // return; // calculate total z distance of the fall float z_diff = m_lastFallZ - movementInfo.z; @@ -18994,7 +19835,7 @@ void Player::HandleFallDamage(MovementInfo& movementInfo) // 14.57 can be calculated by resolving damageperc formular below to 0 if (z_diff >= 14.57f && !isDead() && !isGameMaster() && !HasAuraType(SPELL_AURA_HOVER) && !HasAuraType(SPELL_AURA_FEATHER_FALL) && - !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) ) + !HasAuraType(SPELL_AURA_FLY) && !IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL) ) { //Safe fall, fall height reduction int32 safe_fall = GetTotalAuraModifier(SPELL_AURA_SAFE_FALL); @@ -19089,38 +19930,46 @@ void Player::RemovePossess(bool attack) }*/ } -void Player::SetViewport(uint64 guid, bool moveable) +/*void Player::SetViewport(uint64 guid, bool moveable) { WorldPacket data(SMSG_CLIENT_CONTROL_UPDATE, 8+1); data.appendPackGUID(guid); // Packed guid of object to set client's view to data << (moveable ? uint8(0x01) : uint8(0x00)); // 0 - can't move; 1 - can move m_session->SendPacket(&data); sLog.outDetail("Viewport for "I64FMT" (%s) changed to "I64FMT, GetGUID(), GetName(), guid); +}*/ + +void Player::SetBindSight(Unit *target) +{ + if(target) + target->AddPlayerToVision(this); + else + target->RemovePlayerFromVision(this); } WorldObject* Player::GetFarsightTarget() const { // Players can have in farsight field another player's guid, a creature's guid, or a dynamic object's guid - if (uint64 guid = GetUInt64Value(PLAYER_FARSIGHT)) - return (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*this, guid, TYPEMASK_PLAYER | TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT); + if(uint64 guid = GetFarSight()) + return (WorldObject*)ObjectAccessor::GetObjectByTypeMask(*this, guid, TYPEMASK_FARSIGHTOBJ); return NULL; } void Player::RemoveFarsightTarget() { - if (WorldObject* fTarget = GetFarsightTarget()) + if (WorldObject* target = GetFarsightTarget()) { - if (fTarget->isType(TYPEMASK_PLAYER | TYPEMASK_UNIT)) - ((Unit*)fTarget)->RemovePlayerFromVision(this); + if (target->isType(TYPEMASK_PLAYER | TYPEMASK_UNIT)) + ((Unit*)target)->RemovePlayerFromVision(this); } ClearFarsight(); } void Player::ClearFarsight() { - if (GetUInt64Value(PLAYER_FARSIGHT)) + if(GetFarSight()) { - SetUInt64Value(PLAYER_FARSIGHT, 0); + SetFarSightGUID(0); WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0); GetSession()->SendPacket(&data); } @@ -19134,7 +19983,7 @@ void Player::SetFarsightTarget(WorldObject* obj) // Remove the current target if there is one RemoveFarsightTarget(); - SetUInt64Value(PLAYER_FARSIGHT, obj->GetGUID()); + SetFarSightGUID(obj->GetGUID()); } bool Player::isAllowUseBattleGroundObject() @@ -19149,6 +19998,159 @@ bool Player::isAllowUseBattleGroundObject() ); } +uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair) +{ + uint32 level = getLevel(); + + if(level > GT_MAX_LEVEL) + level = GT_MAX_LEVEL; // max level in this dbc + + uint8 hairstyle = GetByteValue(PLAYER_BYTES, 2); + uint8 haircolor = GetByteValue(PLAYER_BYTES, 3); + uint8 facialhair = GetByteValue(PLAYER_BYTES_2, 0); + + if((hairstyle == newhairstyle) && (haircolor == newhaircolor) && (facialhair == newfacialhair)) + return 0; + + GtBarberShopCostBaseEntry const *bsc = sGtBarberShopCostBaseStore.LookupEntry(level - 1); + + if(!bsc) // shouldn't happen + return 0xFFFFFFFF; + + float cost = 0; + + if(hairstyle != newhairstyle) + cost += bsc->cost; // full price + + if((haircolor != newhaircolor) && (hairstyle == newhairstyle)) + cost += bsc->cost * 0.5f; // +1/2 of price + + if(facialhair != newfacialhair) + cost += bsc->cost * 0.75f; // +3/4 of price + + return uint32(cost); +} + +void Player::InitGlyphsForLevel() +{ + for(uint32 i = 0; i < sGlyphSlotStore.GetNumRows(); ++i) + if(GlyphSlotEntry const * gs = sGlyphSlotStore.LookupEntry(i)) + if(gs->Order) + SetGlyphSlot(gs->Order - 1, gs->Id); + + uint32 level = getLevel(); + uint32 value = 0; + + // 0x3F = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 for 80 level + if(level >= 15) + value |= (0x01 | 0x02); + if(level >= 30) + value |= 0x08; + if(level >= 50) + value |= 0x04; + if(level >= 70) + value |= 0x10; + if(level >= 80) + value |= 0x20; + + SetUInt32Value(PLAYER_GLYPHS_ENABLED, value); +} + +void Player::EnterVehicle(Vehicle *vehicle) +{ + VehicleEntry const *ve = sVehicleStore.LookupEntry(vehicle->GetVehicleId()); + if(!ve) + return; + + VehicleSeatEntry const *veSeat = sVehicleSeatStore.LookupEntry(ve->m_seatID[0]); + if(!veSeat) + return; + + vehicle->SetCharmerGUID(GetGUID()); + vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); + vehicle->setFaction(getFaction()); + + SetCharm(vehicle); // charm + SetMover(vehicle); + SetFarSightGUID(vehicle->GetGUID()); // set view + + SetClientControl(vehicle, 1); // redirect controls to vehicle + + WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); + GetSession()->SendPacket(&data); + + data.Initialize(MSG_MOVE_TELEPORT_ACK, 30); + data.append(GetPackGUID()); + data << uint32(0); // counter? + data << uint32(MOVEMENTFLAG_ONTRANSPORT); // transport + data << uint16(0); // special flags + data << uint32(getMSTime()); // time + data << vehicle->GetPositionX(); // x + data << vehicle->GetPositionY(); // y + data << vehicle->GetPositionZ(); // z + data << vehicle->GetOrientation(); // o + // transport part, TODO: load/calculate seat offsets + data << uint64(vehicle->GetGUID()); // transport guid + data << float(veSeat->m_attachmentOffsetX); // transport offsetX + data << float(veSeat->m_attachmentOffsetY); // transport offsetY + data << float(veSeat->m_attachmentOffsetZ); // transport offsetZ + data << float(0); // transport orientation + data << uint32(getMSTime()); // transport time + data << uint8(0); // seat + // end of transport part + data << uint32(0); // fall time + GetSession()->SendPacket(&data); + + data.Initialize(SMSG_PET_SPELLS, 8+4+4+4+4*10+1+1); + data << uint64(vehicle->GetGUID()); + data << uint32(0x00000000); + data << uint32(0x00000000); + data << uint32(0x00000101); + + for(uint32 i = 0; i < 10; ++i) + data << uint16(0) << uint8(0) << uint8(i+8); + + data << uint8(0); + data << uint8(0); + GetSession()->SendPacket(&data); +} + +void Player::ExitVehicle(Vehicle *vehicle) +{ + vehicle->SetCharmerGUID(0); + vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); + vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H); + + SetCharm(NULL); + SetMover(NULL); + SetFarSightGUID(0); + + SetClientControl(vehicle, 0); + + WorldPacket data(MSG_MOVE_TELEPORT_ACK, 30); + data.append(GetPackGUID()); + data << uint32(0); // counter? + data << uint32(MOVEMENTFLAG_FLY_UNK1); // fly unk + data << uint16(0x40); // special flags + data << uint32(getMSTime()); // time + data << vehicle->GetPositionX(); // x + data << vehicle->GetPositionY(); // y + data << vehicle->GetPositionZ(); // z + data << vehicle->GetOrientation(); // o + data << uint32(0); // fall time + GetSession()->SendPacket(&data); + + data.Initialize(SMSG_PET_SPELLS, 8+4); + data << uint64(0); + data << uint32(0); + GetSession()->SendPacket(&data); + + // only for flyable vehicles? + CastSpell(this, 45472, true); // Parachute +} + bool Player::HasTitle(uint32 bitIndex) { if (bitIndex > 128) @@ -19166,7 +20168,6 @@ void Player::SetTitle(CharTitlesEntry const* title) SetFlag(PLAYER__FIELD_KNOWN_TITLES+fieldIndexOffset, flag); } - /*-----------------------TRINITY--------------------------*/ bool Player::isTotalImmunity() { @@ -19223,3 +20224,207 @@ void Player::UpdateCharmedAI() Attack(target, true); } } + +void Player::ConvertRune(uint8 index, uint8 newType) +{ + SetCurrentRune(index, newType); + + WorldPacket data(SMSG_CONVERT_RUNE, 2); + data << uint8(index); + data << uint8(newType); + GetSession()->SendPacket(&data); +} + +void Player::ResyncRunes(uint8 count) +{ + WorldPacket data(SMSG_RESYNC_RUNES, count * 2); + for(uint32 i = 0; i < count; ++i) + { + data << uint8(GetCurrentRune(i)); // rune type + data << uint8(255 - (GetRuneCooldown(i) * 51)); // passed cooldown time (0-255) + } + GetSession()->SendPacket(&data); +} + +void Player::AddRunePower(uint8 index) +{ + WorldPacket data(SMSG_ADD_RUNE_POWER, 4); + data << uint32(1 << index); // mask (0x00-0x3F probably) + GetSession()->SendPacket(&data); +} + +void Player::InitRunes() +{ + if(getClass() != CLASS_DEATH_KNIGHT) + return; + + m_runes = new Runes; + + m_runes->runeState = 0; + + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + SetBaseRune(i, i / 2); // init base types + SetCurrentRune(i, i / 2); // init current types + SetRuneCooldown(i, 0); // reset cooldowns + m_runes->SetRuneState(i); + } + + for(uint32 i = 0; i < NUM_RUNE_TYPES; ++i) + SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f); +} + +void Player::AutoStoreLoot(uint8 bag, uint8 slot, uint32 loot_id, LootStore const& store, bool broadcast) +{ + Loot loot; + loot.FillLoot (loot_id,store,this,true); + + uint32 max_slot = loot.GetMaxSlotInLootFor(this); + for(uint32 i = 0; i < max_slot; ++i) + { + LootItem* lootItem = loot.LootItemInSlot(i,this); + + ItemPosCountVec dest; + uint8 msg = CanStoreNewItem (bag,slot,dest,lootItem->itemid,lootItem->count); + if(msg != EQUIP_ERR_OK && slot != NULL_SLOT) + msg = CanStoreNewItem( bag, NULL_SLOT,dest,lootItem->itemid,lootItem->count); + if( msg != EQUIP_ERR_OK && bag != NULL_BAG) + msg = CanStoreNewItem( NULL_BAG, NULL_SLOT,dest,lootItem->itemid,lootItem->count); + if(msg != EQUIP_ERR_OK) + { + SendEquipError( msg, NULL, NULL ); + continue; + } + + Item* pItem = StoreNewItem (dest,lootItem->itemid,true,lootItem->randomPropertyId); + SendNewItem(pItem, lootItem->count, false, false, broadcast); + } +} + +uint32 Player::CalculateTalentsPoints() const +{ + uint32 base_talent = getLevel() < 10 ? 0 : uint32((getLevel()-9)*sWorld.getRate(RATE_TALENT)); + + if(getClass() != CLASS_DEATH_KNIGHT) + return base_talent; + + uint32 talentPointsForLevel = + (getLevel() < 56 ? 0 : uint32((getLevel()-55)*sWorld.getRate(RATE_TALENT))) + + m_questRewardTalentCount; + + if(talentPointsForLevel > base_talent) + talentPointsForLevel = base_talent; + + return talentPointsForLevel; +} + +bool Player::IsAllowUseFlyMountsHere() const +{ + if (isGameMaster()) + return true; + + switch(GetVirtualMapForMapAndZone(GetMapId(), GetZoneId())) + { + case 0: + case 1: + //if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_AZEROTH)) + return false; + break; + case 530: + //if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_OUTLAND)) + return false; + break; + case 571: + if(!HasSpell(54197)) + return false; + break; + default: + //if (!sWorld.getConfig(CONFIG_FLYING_MOUNTS_OTHERS)) + return false; + break; + } + return true; +} + +void Player::learnSpellHighRank(uint32 spellid) +{ + learnSpell(spellid,false); + + if(uint32 next = spellmgr.GetNextSpellInChain(spellid)) + learnSpellHighRank(next); +} + +void Player::_LoadSkills() +{ + // Note: skill data itself loaded from `data` field. This is only cleanup part of load + + // reset skill modifiers and set correct unlearn flags + for (uint32 i = 0; i < PLAYER_MAX_SKILLS; i++) + { + SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0); + + // set correct unlearn bit + uint32 id = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF; + if(!id) continue; + + SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(id); + if(!pSkill) continue; + + // enable unlearn button for primary professions only + if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION) + SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,1)); + else + SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0)); + + uint32 vskill = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))); + + learnSkillRewardedSpells(id, vskill); + } + + // special settings + if(getClass()==CLASS_DEATH_KNIGHT) + { + uint32 base_level = std::min(getLevel(),sWorld.getConfig (CONFIG_START_HEROIC_PLAYER_LEVEL)); + if(base_level < 1) + base_level = 1; + uint32 base_skill = (base_level-1)*5; // 270 at starting level 55 + if(base_skill < 1) + base_skill = 1; // skill mast be known and then > 0 in any case + + if(GetPureSkillValue (SKILL_FIRST_AID) < base_skill) + SetSkill(SKILL_FIRST_AID,base_skill, base_skill); + if(GetPureSkillValue (SKILL_AXES) < base_skill) + SetSkill(SKILL_AXES, base_skill,base_skill); + if(GetPureSkillValue (SKILL_DEFENSE) < base_skill) + SetSkill(SKILL_DEFENSE, base_skill,base_skill); + if(GetPureSkillValue (SKILL_POLEARMS) < base_skill) + SetSkill(SKILL_POLEARMS, base_skill,base_skill); + if(GetPureSkillValue (SKILL_SWORDS) < base_skill) + SetSkill(SKILL_SWORDS, base_skill,base_skill); + if(GetPureSkillValue (SKILL_2H_AXES) < base_skill) + SetSkill(SKILL_2H_AXES, base_skill,base_skill); + if(GetPureSkillValue (SKILL_2H_SWORDS) < base_skill) + SetSkill(SKILL_2H_SWORDS, base_skill,base_skill); + if(GetPureSkillValue (SKILL_UNARMED) < base_skill) + SetSkill(SKILL_UNARMED, base_skill,base_skill); + } +} + +uint32 Player::GetPhaseMaskForSpawn() const +{ + uint32 phase = PHASEMASK_NORMAL; + if(!isGameMaster()) + phase = GetPhaseMask(); + else + { + AuraList const& phases = GetAurasByType(SPELL_AURA_PHASE); + if(!phases.empty()) + phase = phases.front()->GetMiscValue(); + } + + // some aura phases include 1 normal map in addition to phase itself + if(uint32 n_phase = phase & ~PHASEMASK_NORMAL) + return n_phase; + + return PHASEMASK_NORMAL; +} diff --git a/src/game/Player.h b/src/game/Player.h index a149e559a3a..7d634b997ee 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,6 +35,7 @@ #include "Pet.h" #include "MapReference.h" #include "Util.h" // for Tokens typedef +#include "AchievementMgr.h" #include<string> #include<vector> @@ -47,8 +48,11 @@ class Pet; class PlayerMenu; class Transport; class UpdateMask; +class SpellCastTargets; class PlayerSocial; class OutdoorPvP; +class AchievementMgr; +class Vehicle; typedef std::deque<Mail*> PlayerMails; @@ -62,6 +66,17 @@ enum SpellModType SPELLMOD_PCT = 108 // SPELL_AURA_ADD_PCT_MODIFIER }; +// 2^n values, Player::m_isunderwater is a bitmask. These are mangos internal values, they are never send to any client +enum PlayerUnderwaterState +{ + UNDERWATER_NONE = 0x00, + UNDERWATER_INWATER = 0x01, // terrain type is water and player is afflicted by it + UNDERWATER_WATER_TRIGGER = 0x02, // m_breathTimer has been initialized + UNDERWATER_WATER_BREATHB = 0x04, // breathbar has been send to client + UNDERWATER_WATER_BREATHB_RETRACTING = 0x10, // breathbar is currently refilling - the player is above water level + UNDERWATER_INLAVA = 0x80 // terrain type is lava and player is afflicted by it +}; + enum PlayerSpellState { PLAYERSPELL_UNCHANGED = 0, @@ -72,27 +87,26 @@ enum PlayerSpellState struct PlayerSpell { - uint16 slotId : 16; PlayerSpellState state : 8; - bool active : 1; - bool disabled : 1; + bool active : 1; // show in spellbook + bool dependent : 1; // learned as result another spell learn, skill grow, quest reward, etc + bool disabled : 1; // first rank has been learned in result talent learn but currently talent unlearned, save max learned ranks }; -#define SPELL_WITHOUT_SLOT_ID uint16(-1) - +// Spell modifier (used for modify other spells) struct SpellModifier { + SpellModifier() : charges(0), lastAffected(NULL) {} SpellModOp op : 8; SpellModType type : 8; int16 charges : 16; int32 value; - uint64 mask; + flag96 mask; uint32 spellId; - uint32 effectId; Spell const* lastAffected; }; -typedef UNORDERED_MAP<uint16, PlayerSpell*> PlayerSpellMap; +typedef UNORDERED_MAP<uint32, PlayerSpell*> PlayerSpellMap; typedef std::list<SpellModifier*> SpellModList; struct SpellCooldown @@ -141,8 +155,6 @@ enum ActionButtonType typedef std::map<uint8,ActionButton> ActionButtonList; -typedef std::pair<uint16, uint8> CreateSpellPair; - struct PlayerCreateInfoItem { PlayerCreateInfoItem(uint32 id, uint32 amount) : item_id(id), item_amount(amount) {} @@ -174,6 +186,8 @@ struct PlayerLevelInfo uint8 stats[MAX_STATS]; }; +typedef std::list<uint32> PlayerCreateInfoSpells; + struct PlayerInfo { // existence checked by displayId != 0 // existence checked by displayId != 0 @@ -189,7 +203,7 @@ struct PlayerInfo uint16 displayId_m; uint16 displayId_f; PlayerCreateInfoItems item; - std::list<CreateSpellPair> spell; + PlayerCreateInfoSpells spell; std::list<uint16> action[4]; PlayerLevelInfo* levelInfo; //[level-1] 0..MaxPlayerLevel-1 @@ -224,6 +238,39 @@ struct Areas float y2; }; +#define MAX_RUNES 6 +#define RUNE_COOLDOWN 5 // 5*2=10 sec + +enum RuneType +{ + RUNE_BLOOD = 0, + RUNE_UNHOLY = 1, + RUNE_FROST = 2, + RUNE_DEATH = 3, + NUM_RUNE_TYPES = 4 +}; + +struct RuneInfo +{ + uint8 BaseRune; + uint8 CurrentRune; + uint8 Cooldown; +}; + +struct Runes +{ + RuneInfo runes[MAX_RUNES]; + uint8 runeState; // mask of available runes + + void SetRuneState(uint8 index, bool set = true) + { + if(set) + runeState |= (1 << index); // usable + else + runeState &= ~(1 << index); // on cooldown + } +}; + enum FactionFlags { FACTION_FLAG_VISIBLE = 0x01, // makes visible in client (set or can be set at interaction with target of this faction) @@ -328,52 +375,6 @@ enum DrunkenState DRUNKEN_SMASHED = 3 }; -enum PlayerStateType -{ - /* - PLAYER_STATE_DANCE - PLAYER_STATE_SLEEP - PLAYER_STATE_SIT - PLAYER_STATE_STAND - PLAYER_STATE_READYUNARMED - PLAYER_STATE_WORK - PLAYER_STATE_POINT(DNR) - PLAYER_STATE_NONE // not used or just no state, just standing there? - PLAYER_STATE_STUN - PLAYER_STATE_DEAD - PLAYER_STATE_KNEEL - PLAYER_STATE_USESTANDING - PLAYER_STATE_STUN_NOSHEATHE - PLAYER_STATE_USESTANDING_NOSHEATHE - PLAYER_STATE_WORK_NOSHEATHE - PLAYER_STATE_SPELLPRECAST - PLAYER_STATE_READYRIFLE - PLAYER_STATE_WORK_NOSHEATHE_MINING - PLAYER_STATE_WORK_NOSHEATHE_CHOPWOOD - PLAYER_STATE_AT_EASE - PLAYER_STATE_READY1H - PLAYER_STATE_SPELLKNEELSTART - PLAYER_STATE_SUBMERGED - */ - - PLAYER_STATE_NONE = 0, - PLAYER_STATE_SIT = 1, - PLAYER_STATE_SIT_CHAIR = 2, - PLAYER_STATE_SLEEP = 3, - PLAYER_STATE_SIT_LOW_CHAIR = 4, - PLAYER_STATE_SIT_MEDIUM_CHAIR = 5, - PLAYER_STATE_SIT_HIGH_CHAIR = 6, - PLAYER_STATE_DEAD = 7, - PLAYER_STATE_KNEEL = 8, - - PLAYER_STATE_FORM_ALL = 0x00FF0000, - - PLAYER_STATE_FLAG_ALWAYS_STAND = 0x01, // byte 4 - PLAYER_STATE_FLAG_CREEP = 0x02000000, - PLAYER_STATE_FLAG_UNTRACKABLE = 0x04000000, - PLAYER_STATE_FLAG_ALL = 0xFF000000, -}; - enum PlayerFlags { PLAYER_FLAGS_GROUP_LEADER = 0x00000001, @@ -382,17 +383,25 @@ enum PlayerFlags PLAYER_FLAGS_GM = 0x00000008, PLAYER_FLAGS_GHOST = 0x00000010, PLAYER_FLAGS_RESTING = 0x00000020, - PLAYER_FLAGS_FFA_PVP = 0x00000080, + PLAYER_FLAGS_UNK7 = 0x00000040, + PLAYER_FLAGS_UNK8 = 0x00000080, // pre-3.0.3 PLAYER_FLAGS_FFA_PVP flag for FFA PVP state PLAYER_FLAGS_CONTESTED_PVP = 0x00000100, // Player has been involved in a PvP combat and will be attacked by contested guards PLAYER_FLAGS_IN_PVP = 0x00000200, PLAYER_FLAGS_HIDE_HELM = 0x00000400, PLAYER_FLAGS_HIDE_CLOAK = 0x00000800, - PLAYER_FLAGS_UNK1 = 0x00001000, // played long time - PLAYER_FLAGS_UNK2 = 0x00002000, // played too long time - PLAYER_FLAGS_UNK3 = 0x00008000, // strange visual effect (2.0.1), looks like PLAYER_FLAGS_GHOST flag - PLAYER_FLAGS_SANCTUARY = 0x00010000, // player entered sanctuary - PLAYER_FLAGS_UNK4 = 0x00020000, // taxi benchmark mode (on/off) (2.0.1) - PLAYER_UNK = 0x00040000, // 2.0.8... + PLAYER_FLAGS_UNK13 = 0x00001000, // played long time + PLAYER_FLAGS_UNK14 = 0x00002000, // played too long time + PLAYER_FLAGS_UNK15 = 0x00004000, + PLAYER_FLAGS_UNK16 = 0x00008000, // strange visual effect (2.0.1), looks like PLAYER_FLAGS_GHOST flag + PLAYER_FLAGS_UNK17 = 0x00010000, // pre-3.0.3 PLAYER_FLAGS_SANCTUARY flag for player entered sanctuary + PLAYER_FLAGS_UNK18 = 0x00020000, // taxi benchmark mode (on/off) (2.0.1) + PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually) + PLAYER_FLAGS_UNK20 = 0x00080000, + PLAYER_FLAGS_UNK21 = 0x00100000, + PLAYER_FLAGS_UNK22 = 0x00200000, + PLAYER_FLAGS_UNK23 = 0x00400000, + PLAYER_ALLOW_ONLY_ABILITY = 0x00800000, // used by bladestorm and killing spree + PLAYER_FLAGS_UNK25 = 0x01000000 // disabled all melee ability on tab include autoattack }; // used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1) @@ -481,7 +490,8 @@ enum LootType LOOT_DISENCHANTING = 5, // unsupported by client, sending LOOT_SKINNING instead LOOT_PROSPECTING = 6, // unsupported by client, sending LOOT_SKINNING instead LOOT_INSIGNIA = 7, // unsupported by client, sending LOOT_SKINNING instead - LOOT_FISHINGHOLE = 8 // unsupported by client, sending LOOT_FISHING instead + LOOT_FISHINGHOLE = 8, // unsupported by client, sending LOOT_FISHING instead + LOOT_MILLING = 9 // unsupported by client, sending LOOT_SKINNING instead }; enum MirrorTimerType @@ -511,7 +521,8 @@ enum AtLoginFlags AT_LOGIN_NONE = 0, AT_LOGIN_RENAME = 1, AT_LOGIN_RESET_SPELLS = 2, - AT_LOGIN_RESET_TALENTS = 4 + AT_LOGIN_RESET_TALENTS = 4, + AT_LOGIN_CUSTOMIZE = 8 }; typedef std::map<uint32, QuestStatusData> QuestStatusMap; @@ -543,7 +554,7 @@ enum PlayerSlots // first slot for item stored (in any way in player m_items data) PLAYER_SLOT_START = 0, // last+1 slot for item stored (in any way in player m_items data) - PLAYER_SLOT_END = 118, + PLAYER_SLOT_END = 200, PLAYER_SLOTS_COUNT = (PLAYER_SLOT_END - PLAYER_SLOT_START) }; @@ -671,12 +682,30 @@ enum KeyRingSlots KEYRING_SLOT_END = 118 }; +enum VanityPetSlots +{ + VANITYPET_SLOT_START = 118, // not use, vanity pets stored as spells + VANITYPET_SLOT_END = 136 // not alloed any content in. +}; + +enum CurrencyTokenSlots +{ + CURRENCYTOKEN_SLOT_START = 136, + CURRENCYTOKEN_SLOT_END = 168 +}; + +enum QuestBagSlots +{ + QUESTBAG_SLOT_START = 168, + QUESTBAG_SLOT_END = 200 +}; + struct ItemPosCount { - ItemPosCount(uint16 _pos, uint8 _count) : pos(_pos), count(_count) {} + ItemPosCount(uint16 _pos, uint32 _count) : pos(_pos), count(_count) {} bool isContainedIn(std::vector<ItemPosCount> const& vec) const; uint16 pos; - uint8 count; + uint32 count; }; typedef std::vector<ItemPosCount> ItemPosCountVec; @@ -689,14 +718,15 @@ enum TradeSlots enum TransferAbortReason { - TRANSFER_ABORT_MAX_PLAYERS = 0x0001, // Transfer Aborted: instance is full - TRANSFER_ABORT_NOT_FOUND = 0x0002, // Transfer Aborted: instance not found - TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x0003, // You have entered too many instances recently. - TRANSFER_ABORT_ZONE_IN_COMBAT = 0x0005, // Unable to zone in while an encounter is in progress. - TRANSFER_ABORT_INSUF_EXPAN_LVL1 = 0x0106, // You must have TBC expansion installed to access this area. - TRANSFER_ABORT_DIFFICULTY1 = 0x0007, // Normal difficulty mode is not available for %s. - TRANSFER_ABORT_DIFFICULTY2 = 0x0107, // Heroic difficulty mode is not available for %s. - TRANSFER_ABORT_DIFFICULTY3 = 0x0207 // Epic difficulty mode is not available for %s. + TRANSFER_ABORT_ERROR = 0x00, + TRANSFER_ABORT_MAX_PLAYERS = 0x01, // Transfer Aborted: instance is full + TRANSFER_ABORT_NOT_FOUND = 0x02, // Transfer Aborted: instance not found + TRANSFER_ABORT_TOO_MANY_INSTANCES = 0x03, // You have entered too many instances recently. + TRANSFER_ABORT_ZONE_IN_COMBAT = 0x05, // Unable to zone in while an encounter is in progress. + TRANSFER_ABORT_INSUF_EXPAN_LVL = 0x06, // You must have <TBC,WotLK> expansion installed to access this area. + TRANSFER_ABORT_DIFFICULTY = 0x07, // <Normal,Heroic,Epic> difficulty mode is not available for %s. + TRANSFER_ABORT_UNIQUE_MESSAGE = 0x08, // Until you've escaped TLK's grasp, you cannot leave this place! + TRANSFER_ABORT_TOO_MANY_REALM_INSTANCES = 0x09 // Additional instances cannot be launched, please try again later. }; enum InstanceResetWarningType @@ -710,15 +740,16 @@ enum InstanceResetWarningType struct MovementInfo { // common - //uint32 flags; - uint8 unk1; + uint32 flags; + uint16 unk1; uint32 time; float x, y, z, o; // transport uint64 t_guid; float t_x, t_y, t_z, t_o; uint32 t_time; - // swimming and unk + int8 t_seat; + // swimming and unknown float s_pitch; // last fall time uint32 fallTime; @@ -729,17 +760,17 @@ struct MovementInfo MovementInfo() { - //flags = + flags = 0; time = t_time = fallTime = 0; unk1 = 0; x = y = z = o = t_x = t_y = t_z = t_o = s_pitch = j_unk = j_sinAngle = j_cosAngle = j_xyspeed = u_unk1 = 0.0f; t_guid = 0; } - /*void SetMovementFlags(uint32 _flags) + void SetMovementFlags(uint32 _flags) { flags = _flags; - }*/ + } }; // flags that use in movement check for example at spell casting @@ -812,10 +843,12 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16, PLAYER_LOGIN_QUERY_LOADGUILD = 17, PLAYER_LOGIN_QUERY_LOADARENAINFO = 18, - - MAX_PLAYER_LOGIN_QUERY + PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS = 19, + PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS = 20, + MAX_PLAYER_LOGIN_QUERY = 21 }; + // Player summoning auto-decline time (in secs) #define MAX_PLAYER_SUMMON_DELAY (2*MINUTE) #define MAX_MONEY_AMOUNT (0x7FFFFFFF-1) @@ -836,11 +869,9 @@ class TRINITY_DLL_SPEC PlayerTaxi PlayerTaxi(); ~PlayerTaxi() {} // Nodes - void InitTaxiNodesForLevel(uint32 race, uint32 level); + void InitTaxiNodesForLevel(uint32 race, uint32 chrClass, uint32 level); void LoadTaxiMask(const char* data); - void SaveTaxiMask(const char* data); - uint32 GetTaximask( uint8 index ) const { return m_taximask[index]; } bool IsTaximaskNodeKnown(uint32 nodeidx) const { uint8 field = uint8((nodeidx - 1) / 32); @@ -862,7 +893,7 @@ class TRINITY_DLL_SPEC PlayerTaxi void AppendTaximaskTo(ByteBuffer& data,bool all); // Destinations - bool LoadTaxiDestinationsFromString(const std::string& values); + bool LoadTaxiDestinationsFromString(const std::string& values, uint32 team); std::string SaveTaxiDestinationsToString(); void ClearTaxiDestinations() { m_TaxiDestinations.clear(); } @@ -876,11 +907,15 @@ class TRINITY_DLL_SPEC PlayerTaxi return GetTaxiDestination(); } bool empty() const { return m_TaxiDestinations.empty(); } + + friend std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi); private: TaxiMask m_taximask; std::deque<uint32> m_TaxiDestinations; }; +std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi); + class TRINITY_DLL_SPEC Player : public Unit { friend class WorldSession; @@ -898,23 +933,6 @@ class TRINITY_DLL_SPEC Player : public Unit void AddToWorld(); void RemoveFromWorld(); - void SetViewport(uint64 guid, bool movable); - void RemovePossess(bool attack = true); - void StopCharmOrPossess() - { - if(isPossessing()) - RemovePossess(true); - else if(GetCharm()) - Uncharm(); - } - WorldObject* GetFarsightTarget() const; - void ClearFarsight(); - void RemoveFarsightTarget(); - void SetFarsightTarget(WorldObject* target); - // Controls if vision is currently on farsight object, updated in FAR_SIGHT opcode - void SetFarsightVision(bool apply) { m_farsightVision = apply; } - bool HasFarsightVision() const { return m_farsightVision; } - bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0); bool TeleportTo(WorldLocation const &loc, uint32 options = 0) @@ -945,7 +963,7 @@ class TRINITY_DLL_SPEC Player : public Unit void SendInitialPacketsBeforeAddToMap(); void SendInitialPacketsAfterAddToMap(); - void SendTransferAborted(uint32 mapid, uint16 reason); + void SendTransferAborted(uint32 mapid, uint8 reason, uint8 arg = 0); void SendInstanceResetWarning(uint32 mapid, uint32 time); bool CanInteractWithNPCs(bool alive = true) const; @@ -958,10 +976,12 @@ class TRINITY_DLL_SPEC Player : public Unit std::string afkMsg; std::string dndMsg; + uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair); + PlayerSocial *GetSocial() { return m_social; } PlayerTaxi m_taxi; - void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(),getLevel()); } + void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(), getClass(), getLevel()); } bool ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_id = 0 , Creature* npc = NULL); // mount_id can be used in scripting calls bool isAcceptWhispers() const { return m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS; } @@ -1021,6 +1041,7 @@ class TRINITY_DLL_SPEC Player : public Unit void AddGuardian(Pet* pet) { m_guardianPets.insert(pet->GetGUID()); } GuardianPetList const& GetGuardians() const { return m_guardianPets; } void Uncharm(); + uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn void Say(const std::string& text, const uint32 language); void Yell(const std::string& text, const uint32 language); @@ -1039,9 +1060,15 @@ class TRINITY_DLL_SPEC Player : public Unit Item* GetItemByGuid( uint64 guid ) const; Item* GetItemByPos( uint16 pos ) const; Item* GetItemByPos( uint8 bag, uint8 slot ) const; + inline Item* GetUseableItemByPos( uint8 bag, uint8 slot ) const //Does additional check for disarmed weapons + { + if (!CanUseAttackType(GetAttackBySlot(slot))) + return NULL; + return GetItemByPos(bag, slot); + } Item* GetWeaponForAttack(WeaponAttackType attackType, bool useable = false) const; Item* GetShield(bool useable = false) const; - static uint32 GetAttackBySlot( uint8 slot ); // MAX_ATTACK if not weapon slot + static uint8 GetAttackBySlot( uint8 slot ); // MAX_ATTACK if not weapon slot std::vector<Item *> &GetItemUpdateQueue() { return m_itemUpdateQueue; } static bool IsInventoryPos( uint16 pos ) { return IsInventoryPos(pos >> 8,pos & 255); } static bool IsInventoryPos( uint8 bag, uint8 slot ); @@ -1055,6 +1082,7 @@ class TRINITY_DLL_SPEC Player : public Unit bool HasBankBagSlot( uint8 slot ) const; bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const; bool HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem = NULL); + bool CanNoReagentCast(SpellEntry const* spellInfo) const; Item* GetItemOrItemWithGemEquipped( uint32 item ) const; uint8 CanTakeMoreSimilarItems(Item* pItem) const { return _CanTakeMoreSimilarItems(pItem->GetEntry(),pItem->GetCount(),pItem); } uint8 CanTakeMoreSimilarItems(uint32 entry, uint32 count) const { return _CanTakeMoreSimilarItems(entry,count,NULL); } @@ -1086,6 +1114,8 @@ class TRINITY_DLL_SPEC Player : public Unit Item* EquipItem( uint16 pos, Item *pItem, bool update ); void AutoUnequipOffhandIfNeed(); bool StoreNewItemInBestSlots(uint32 item_id, uint32 item_count); + void AutoStoreLoot(uint8 bag, uint8 slot, uint32 loot_id, LootStore const& store, bool broadcast = false); + void AutoStoreLoot(uint32 loot_id, LootStore const& store, bool broadcast = false) { AutoStoreLoot(NULL_BAG,NULL_SLOT,loot_id,store,broadcast); } uint8 _CanTakeMoreSimilarItems(uint32 entry, uint32 count, Item* pItem, uint32* no_space_count = NULL) const; uint8 _CanStoreItem( uint8 bag, uint8 slot, ItemPosCountVec& dest, uint32 entry, uint32 count, Item *pItem = NULL, bool swap = false, uint32* no_space_count = NULL ) const; @@ -1128,10 +1158,10 @@ class TRINITY_DLL_SPEC Player : public Unit uint32 GetWeaponProficiency() const { return m_WeaponProficiency; } uint32 GetArmorProficiency() const { return m_ArmorProficiency; } bool IsInFeralForm() const { return m_form == FORM_CAT || m_form == FORM_BEAR || m_form == FORM_DIREBEAR; } - bool IsUseEquipedWeapon( bool mainhand ) const + bool IsTwoHandUsed() const { - // disarm applied only to mainhand weapon - return !IsInFeralForm() && (!mainhand || !HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISARMED) ); + Item* mainItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); + return mainItem && mainItem->GetProto()->InventoryType == INVTYPE_2HWEAPON && !CanTitanGrip(); } void SendNewItem( Item *item, uint32 count, bool received, bool created, bool broadcast = false ); bool BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint64 bagguid, uint8 slot); @@ -1230,7 +1260,6 @@ class TRINITY_DLL_SPEC Player : public Unit } } uint32 GetReqKillOrCastCurrentCount(uint32 quest_id, int32 entry); - void AdjustQuestReqItemCount( Quest const* pQuest ); void AreaExploredOrEventHappens( uint32 questId ); void GroupEventHappens( uint32 questId, WorldObject const* pEventObject ); void ItemAddedQuestCheck( uint32 entry, uint32 count ); @@ -1267,6 +1296,7 @@ class TRINITY_DLL_SPEC Player : public Unit /*********************************************************/ bool LoadFromDB(uint32 guid, SqlQueryHolder *holder); + bool MinimalLoadFromDB(QueryResult *result, uint32 guid); static bool LoadValuesArrayFromDB(Tokens& data,uint64 guid); static uint32 GetUInt32ValueFromArray(Tokens const& data, uint16 index); @@ -1288,6 +1318,7 @@ class TRINITY_DLL_SPEC Player : public Unit static void SetFloatValueInArray(Tokens& data,uint16 index, float value); static void SetUInt32ValueInDB(uint16 index, uint32 value, uint64 guid); static void SetFloatValueInDB(uint16 index, float value, uint64 guid); + static void Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair); static void SavePositionInDB(uint32 mapid, float x,float y,float z,float o,uint32 zone,uint64 guid); bool m_mailsLoaded; @@ -1344,7 +1375,7 @@ class TRINITY_DLL_SPEC Player : public Unit void SetSelection(const uint64 &guid) { m_curSelection = guid; SetUInt64Value(UNIT_FIELD_TARGET, guid); } uint8 GetComboPoints() { return m_comboPoints; } - uint64 GetComboTarget() { return m_comboTarget; } + const uint64& GetComboTarget() const { return m_comboTarget; } void AddComboPoints(Unit* target, int8 count); void ClearComboPoints(); @@ -1380,10 +1411,7 @@ class TRINITY_DLL_SPEC Player : public Unit Item* GetMItem(uint32 id) { ItemMap::const_iterator itr = mMitems.find(id); - if (itr != mMitems.end()) - return itr->second; - - return NULL; + return itr != mMitems.end() ? itr->second : NULL; } void AddMItem(Item* it) @@ -1395,30 +1423,28 @@ class TRINITY_DLL_SPEC Player : public Unit bool RemoveMItem(uint32 id) { - ItemMap::iterator i = mMitems.find(id); - if (i == mMitems.end()) - return false; - - mMitems.erase(i); - return true; + return mMitems.erase(id) ? true : false; } void PetSpellInitialize(); void CharmSpellInitialize(); void PossessSpellInitialize(); bool HasSpell(uint32 spell) const; + bool HasActiveSpell(uint32 spell) const; // show in spellbook TrainerSpellState GetTrainerSpellState(TrainerSpell const* trainer_spell) const; bool IsSpellFitByClassAndRace( uint32 spell_id ) const; + bool IsNeedCastPassiveSpellAtLearn(SpellEntry const* spellInfo) const; void SendProficiency(uint8 pr1, uint32 pr2); void SendInitialSpells(); - bool addSpell(uint32 spell_id, bool active, bool learning = true, bool loading = false, uint16 slot_id=SPELL_WITHOUT_SLOT_ID, bool disabled = false); - void learnSpell(uint32 spell_id); - void removeSpell(uint32 spell_id, bool disabled = false); + bool addSpell(uint32 spell_id, bool active, bool learning, bool dependent, bool disabled); + void learnSpell(uint32 spell_id, bool dependent); + void removeSpell(uint32 spell_id, bool disabled = false, bool update_action_bar_for_low_rank = false); void resetSpells(); - void learnDefaultSpells(bool loading = false); + void learnDefaultSpells(); void learnQuestRewardedSpells(); void learnQuestRewardedSpells(Quest const* quest); + void learnSpellHighRank(uint32 spellid); uint32 GetFreeTalentPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS1); } void SetFreeTalentPoints(uint32 points) { SetUInt32Value(PLAYER_CHARACTER_POINTS1,points); } @@ -1426,6 +1452,14 @@ class TRINITY_DLL_SPEC Player : public Unit uint32 resetTalentsCost() const; void InitTalentForLevel(); + uint32 CalculateTalentsPoints() const; + + void InitGlyphsForLevel(); + void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); } + uint32 GetGlyphSlot(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); } + void SetGlyph(uint8 slot, uint32 glyph) { SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph); } + uint32 GetGlyph(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot); } + uint32 GetFreePrimaryProffesionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); } void SetFreePrimaryProffesions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2,profs); } void InitPrimaryProffesions(); @@ -1434,8 +1468,6 @@ class TRINITY_DLL_SPEC Player : public Unit PlayerSpellMap & GetSpellMap() { return m_spells; } void AddSpellMod(SpellModifier* mod, bool apply); - int32 GetTotalFlatMods(uint32 spellId, SpellModOp op); - int32 GetTotalPctMods(uint32 spellId, SpellModOp op); bool IsAffectedBySpellmod(SpellEntry const *spellInfo, SpellModifier *mod, Spell const* spell = NULL); template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL); void RemoveSpellMods(Spell const* spell); @@ -1540,6 +1572,7 @@ class TRINITY_DLL_SPEC Player : public Unit static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot); void SetArenaTeamIdInvited(uint32 ArenaTeamId) { m_ArenaTeamIdInvited = ArenaTeamId; } uint32 GetArenaTeamIdInvited() { return m_ArenaTeamIdInvited; } + static void LeaveAllArenaTeams(uint64 guid); void SetDifficulty(uint32 dungeon_difficulty) { m_dungeonDifficulty = dungeon_difficulty; } uint8 GetDifficulty() { return m_dungeonDifficulty; } @@ -1565,9 +1598,12 @@ class TRINITY_DLL_SPEC Player : public Unit void UpdateArmor(); void UpdateMaxHealth(); void UpdateMaxPower(Powers power); + void ApplyFeralAPBonus(int32 amount, bool apply); void UpdateAttackPowerAndDamage(bool ranged = false); void UpdateShieldBlockValue(); void UpdateDamagePhysical(WeaponAttackType attType); + void ApplySpellDamageBonus(int32 amount, bool apply); + void ApplySpellHealingBonus(int32 amount, bool apply); void UpdateSpellDamageAndHealingBonus(); void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, float& min_damage, float& max_damage); @@ -1585,6 +1621,8 @@ class TRINITY_DLL_SPEC Player : public Unit uint32 GetRangedCritDamageReduction(uint32 damage) const; uint32 GetSpellCritDamageReduction(uint32 damage) const; uint32 GetDotDamageReduction(uint32 damage) const; + uint32 GetBaseSpellDamageBonus() { return m_baseSpellDamage;} + uint32 GetBaseSpellHealingBonus() { return m_baseSpellHealing;} float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType) const; void UpdateBlockPercentage(); @@ -1592,9 +1630,14 @@ class TRINITY_DLL_SPEC Player : public Unit void UpdateAllCritPercentages(); void UpdateParryPercentage(); void UpdateDodgePercentage(); + void UpdateMeleeHitChances(); + void UpdateRangedHitChances(); + void UpdateSpellHitChances(); + void UpdateAllSpellCritChances(); void UpdateSpellCritChance(uint32 school); void UpdateExpertise(WeaponAttackType attType); + void ApplyManaRegenBonus(int32 amount, bool apply); void UpdateManaRegen(); const uint64& GetLootGUID() const { return m_lootGuid; } @@ -1671,18 +1714,18 @@ class TRINITY_DLL_SPEC Player : public Unit void UpdateDefense(); void UpdateWeaponSkill (WeaponAttackType attType); - void UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, MeleeHitOutcome outcome, bool defence); + void UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, bool defence); void SetSkill(uint32 id, uint16 currVal, uint16 maxVal); - uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + uint16 GetMaxSkillValue(uint32 skill) const; // max + perm. bonus + temp bonus uint16 GetPureMaxSkillValue(uint32 skill) const; // max uint16 GetSkillValue(uint32 skill) const; // skill value + perm. bonus + temp bonus uint16 GetBaseSkillValue(uint32 skill) const; // skill value + perm. bonus uint16 GetPureSkillValue(uint32 skill) const; // skill value + int16 GetSkillPermBonusValue(uint32 skill) const; int16 GetSkillTempBonusValue(uint32 skill) const; bool HasSkill(uint32 skill) const; - void learnSkillRewardedSpells( uint32 id ); - void learnSkillRewardedSpells(); + void learnSkillRewardedSpells(uint32 id, uint32 value); void SetDontMove(bool dontMove); bool GetDontMove() const { return m_dontMove; } @@ -1696,6 +1739,7 @@ class TRINITY_DLL_SPEC Player : public Unit bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const; bool RewardPlayerAndGroupAtKill(Unit* pVictim); + bool isHonorOrXPTarget(Unit* pVictim); FactionStateList m_factions; ForcedReactions m_forcedReactions; @@ -1762,6 +1806,8 @@ class TRINITY_DLL_SPEC Player : public Unit void SetCanParry(bool value); bool CanBlock() const { return m_canBlock; } void SetCanBlock(bool value); + bool CanTitanGrip() const { return m_canTitanGrip ; } + void SetCanTitanGrip(bool value) { m_canTitanGrip = value; } void SetRegularAttackTime(); void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[modGroup][modType] = value; } @@ -1790,12 +1836,13 @@ class TRINITY_DLL_SPEC Player : public Unit void ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply, bool form_change = false); void UpdateEquipSpellsAtFormChange(); void CastItemCombatSpell(Item *item,Unit* Target, WeaponAttackType attType); + void CastItemUseSpell(Item *item,SpellCastTargets const& targets,uint8 cast_count, uint32 glyphIndex); void SendInitWorldStates(bool force = false, uint32 forceZoneId = 0); void SendUpdateWorldState(uint32 Field, uint32 Value); void SendDirectMessage(WorldPacket *data); - void SendAuraDurationsForTarget(Unit* target); + void SendAurasForTarget(Unit *target); PlayerMenu* PlayerTalkClass; std::vector<ItemSetEffect *> ItemSetEff; @@ -1892,18 +1939,10 @@ class TRINITY_DLL_SPEC Player : public Unit return true; return false; } - uint32 GetBattleGroundEntryPointMap() const { return m_bgEntryPointMap; } - float GetBattleGroundEntryPointX() const { return m_bgEntryPointX; } - float GetBattleGroundEntryPointY() const { return m_bgEntryPointY; } - float GetBattleGroundEntryPointZ() const { return m_bgEntryPointZ; } - float GetBattleGroundEntryPointO() const { return m_bgEntryPointO; } + WorldLocation const& GetBattleGroundEntryPoint() const { return m_bgEntryPoint; } void SetBattleGroundEntryPoint(uint32 Map, float PosX, float PosY, float PosZ, float PosO ) { - m_bgEntryPointMap = Map; - m_bgEntryPointX = PosX; - m_bgEntryPointY = PosY; - m_bgEntryPointZ = PosZ; - m_bgEntryPointO = PosO; + m_bgEntryPoint = WorldLocation(Map,PosX,PosY,PosZ,PosO); } void SetBGTeam(uint32 team) { m_bgTeam = team; } @@ -1915,7 +1954,7 @@ class TRINITY_DLL_SPEC Player : public Unit void ReportedAfkBy(Player* reporter); void ClearAfkReports() { m_bgAfkReporter.clear(); } - bool GetBGAccessByLevel(uint32 bgTypeId) const; + bool GetBGAccessByLevel(BattleGroundTypeId bgTypeId) const; bool isAllowUseBattleGroundObject(); bool isTotalImmunity(); @@ -1956,6 +1995,7 @@ class TRINITY_DLL_SPEC Player : public Unit MovementInfo m_movementInfo; uint32 m_lastFallTime; float m_lastFallZ; + Unit *m_mover; void SetFallInformation(uint32 time, float z) { m_lastFallTime = time; @@ -1966,6 +2006,7 @@ class TRINITY_DLL_SPEC Player : public Unit bool CanFly() const { return HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY); } bool IsFlying() const { return HasUnitMovementFlag(MOVEMENTFLAG_FLYING); } + bool IsAllowUseFlyMountsHere() const; void HandleDrowning(); void HandleFallDamage(MovementInfo& movementInfo); @@ -1973,8 +2014,30 @@ class TRINITY_DLL_SPEC Player : public Unit void SetClientControl(Unit* target, uint8 allowMove); + void EnterVehicle(Vehicle *vehicle); + void ExitVehicle(Vehicle *vehicle); + + //void SetViewport(uint64 guid, bool movable); + void SetMover(Unit* target) { m_mover = target ? target : this; } + void RemovePossess(bool attack = true); + void StopCharmOrPossess() + { + if(isPossessing()) + RemovePossess(true); + else if(GetCharm()) + Uncharm(); + } + uint64 GetFarSight() const { return GetUInt64Value(PLAYER_FARSIGHT); } - void SetFarSight(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); } + void SetFarSightGUID(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); } + void SetBindSight(Unit *target); + WorldObject* GetFarsightTarget() const; + void ClearFarsight(); + void RemoveFarsightTarget(); + void SetFarsightTarget(WorldObject* target); + // Controls if vision is currently on farsight object, updated in FAR_SIGHT opcode + void SetFarsightVision(bool apply) { m_farsightVision = apply; } + bool HasFarsightVision() const { return m_farsightVision; } // Transports Transport * GetTransport() const { return m_transport; } @@ -1985,6 +2048,7 @@ class TRINITY_DLL_SPEC Player : public Unit float GetTransOffsetZ() const { return m_movementInfo.t_z; } float GetTransOffsetO() const { return m_movementInfo.t_o; } uint32 GetTransTime() const { return m_movementInfo.t_time; } + int8 GetTransSeat() const { return m_movementInfo.t_seat; } uint32 GetSaveTimer() const { return m_nextSave; } void SetSaveTimer(uint32 timer) { m_nextSave = timer; } @@ -2003,6 +2067,7 @@ class TRINITY_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); } // currently visible objects at player client typedef std::set<uint64> ClientGUIDs; @@ -2036,7 +2101,6 @@ class TRINITY_DLL_SPEC Player : public Unit uint32 GetOldPetSpell() const { return m_oldpetspell; } void SetOldPetSpell(uint32 petspell) { m_oldpetspell = petspell; } - /*********************************************************/ /*** INSTANCE SYSTEM ***/ /*********************************************************/ @@ -2069,11 +2133,10 @@ class TRINITY_DLL_SPEC Player : public Unit GroupReference& GetGroupRef() { return m_group; } void SetGroup(Group *group, int8 subgroup = -1); uint8 GetSubGroup() const { return m_group.getSubGroup(); } - uint32 GetGroupUpdateFlag() { return m_groupUpdateMask; } + uint32 GetGroupUpdateFlag() const { return m_groupUpdateMask; } void SetGroupUpdateFlag(uint32 flag) { m_groupUpdateMask |= flag; } - uint64 GetAuraUpdateMask() { return m_auraUpdateMask; } - void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } - void UnsetAuraUpdateMask(uint8 slot) { m_auraUpdateMask &= ~(uint64(1) << slot); } + const uint64& GetAuraUpdateMaskForRaid() const { return m_auraRaidUpdateMask; } + void SetAuraUpdateMaskForRaid(uint8 slot) { m_auraRaidUpdateMask |= (uint64(1) << slot); } Player* GetNextRandomRaidMember(float radius); PartyResult CanUninviteFromGroup() const; @@ -2085,6 +2148,18 @@ class TRINITY_DLL_SPEC Player : public Unit WorldLocation& GetTeleportDest() { return m_teleport_dest; } DeclinedName const* GetDeclinedNames() const { return m_declinedname; } + uint8 GetRunesState() const { return m_runes->runeState; } + uint8 GetBaseRune(uint8 index) const { return m_runes->runes[index].BaseRune; } + uint8 GetCurrentRune(uint8 index) const { return m_runes->runes[index].CurrentRune; } + uint8 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; } + void SetBaseRune(uint8 index, uint8 baseRune) { m_runes->runes[index].BaseRune = baseRune; } + void SetCurrentRune(uint8 index, uint8 currentRune) { m_runes->runes[index].CurrentRune = currentRune; } + void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].Cooldown = cooldown; m_runes->SetRuneState(index, (cooldown == 0) ? true : false); } + void ConvertRune(uint8 index, uint8 newType); + void ResyncRunes(uint8 count); + void AddRunePower(uint8 index); + void InitRunes(); + AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } bool HasTitle(uint32 bitIndex); bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); } void SetTitle(CharTitlesEntry const* title); @@ -2106,11 +2181,7 @@ class TRINITY_DLL_SPEC Player : public Unit uint32 invitedToInstance; }; BgBattleGroundQueueID_Rec m_bgBattleGroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES]; - uint32 m_bgEntryPointMap; - float m_bgEntryPointX; - float m_bgEntryPointY; - float m_bgEntryPointZ; - float m_bgEntryPointO; + WorldLocation m_bgEntryPoint; std::set<uint32> m_bgAfkReporter; uint8 m_bgAfkReportedCount; @@ -2134,6 +2205,7 @@ class TRINITY_DLL_SPEC Player : public Unit void _LoadActions(QueryResult *result); void _LoadAuras(QueryResult *result, uint32 timediff); + void _LoadGlyphAuras(); void _LoadBoundInstances(QueryResult *result); void _LoadInventory(QueryResult *result, uint32 timediff); void _LoadMailInit(QueryResult *resultUnread, QueryResult *resultDelivery); @@ -2143,6 +2215,7 @@ class TRINITY_DLL_SPEC Player : public Unit void _LoadDailyQuestStatus(QueryResult *result); void _LoadGroup(QueryResult *result); void _LoadReputation(QueryResult *result); + void _LoadSkills(); void _LoadSpells(QueryResult *result); void _LoadTutorials(QueryResult *result); void _LoadFriendList(QueryResult *result); @@ -2184,7 +2257,6 @@ class TRINITY_DLL_SPEC Player : public Unit time_t m_lastHonorUpdateTime; void outDebugValues() const; - bool _removeSpell(uint16 spell_id); uint64 m_lootGuid; uint32 m_race; @@ -2221,6 +2293,11 @@ class TRINITY_DLL_SPEC Player : public Unit ActionButtonList m_actionButtons; float m_auraBaseMod[BASEMOD_END][MOD_END]; + int16 m_baseRatingValue[MAX_COMBAT_RATING]; + uint16 m_baseSpellDamage; + uint16 m_baseSpellHealing; + uint16 m_baseFeralAP; + uint16 m_baseManaRegen; SpellModList m_spellMods[MAX_SPELLMOD]; int32 m_SpellModRemoveCount; @@ -2254,7 +2331,6 @@ class TRINITY_DLL_SPEC Player : public Unit bool m_DailyQuestChanged; time_t m_lastDailyQuestTime; - uint32 m_regenTimer; uint32 m_breathTimer; uint32 m_drunkTimer; uint16 m_drunk; @@ -2273,8 +2349,10 @@ class TRINITY_DLL_SPEC Player : public Unit uint32 m_ArmorProficiency; bool m_canParry; bool m_canBlock; + bool m_canTitanGrip; uint8 m_swingErrorMsg; float m_ammoDPS; + ////////////////////Rest System///////////////////// int time_inn_enter; uint32 inn_pos_mapid; @@ -2291,6 +2369,7 @@ class TRINITY_DLL_SPEC Player : public Unit uint32 m_resetTalentsCost; time_t m_resetTalentsTime; uint32 m_usedTalentCount; + uint32 m_questRewardTalentCount; // Social PlayerSocial *m_social; @@ -2299,7 +2378,7 @@ class TRINITY_DLL_SPEC Player : public Unit GroupReference m_group; Group *m_groupInvite; uint32 m_groupUpdateMask; - uint64 m_auraUpdateMask; + uint64 m_auraRaidUpdateMask; // Temporarily removed pet cache uint32 m_temporaryUnsummonedPetNumber; @@ -2321,6 +2400,8 @@ class TRINITY_DLL_SPEC Player : public Unit bool m_farsightVision; DeclinedName *m_declinedname; + Runes *m_runes; + AchievementMgr m_achievementMgr; private: // internal common parts for CanStore/StoreItem functions uint8 _CanStoreItem_InSpecificSlot( uint8 bag, uint8 slot, ItemPosCountVec& dest, ItemPrototype const *pProto, uint32& count, bool swap, Item *pSrcItem ) const; @@ -2328,6 +2409,8 @@ class TRINITY_DLL_SPEC Player : public Unit uint8 _CanStoreItem_InInventorySlots( uint8 slot_begin, uint8 slot_end, ItemPosCountVec& dest, ItemPrototype const *pProto, uint32& count, bool merge, Item *pSrcItem, uint8 skip_bag, uint8 skip_slot ) const; Item* _StoreItem( uint16 pos, Item *pItem, uint32 count, bool clone, bool update ); + void AdjustQuestReqItemCount( Quest const* pQuest, QuestStatusData& questStatusData ); + GridReference<Player> m_gridRef; MapReference m_mapRef; diff --git a/src/game/PlayerDump.cpp b/src/game/PlayerDump.cpp index fb22e963ca0..d698e8c293c 100644 --- a/src/game/PlayerDump.cpp +++ b/src/game/PlayerDump.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/PlayerDump.h b/src/game/PlayerDump.h index c8335216716..365406beede 100644 --- a/src/game/PlayerDump.h +++ b/src/game/PlayerDump.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/PointMovementGenerator.cpp b/src/game/PointMovementGenerator.cpp index a4795974e96..bcc25987e56 100644 --- a/src/game/PointMovementGenerator.cpp +++ b/src/game/PointMovementGenerator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/PointMovementGenerator.h b/src/game/PointMovementGenerator.h index 8a3f0da675f..08050b24e3d 100644 --- a/src/game/PointMovementGenerator.h +++ b/src/game/PointMovementGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/PossessedAI.cpp b/src/game/PossessedAI.cpp index f291221216a..7ac36a37352 100644 --- a/src/game/PossessedAI.cpp +++ b/src/game/PossessedAI.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * - * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> + * Thanks to the original authors: MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/PossessedAI.h b/src/game/PossessedAI.h index 5c4a670c200..5671cfa912d 100644 --- a/src/game/PossessedAI.h +++ b/src/game/PossessedAI.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * - * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/> + * Thanks to the original authors: MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp index 9f9eecc2234..681318a9de9 100644 --- a/src/game/QueryHandler.cpp +++ b/src/game/QueryHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,7 @@ #include "NPCHandler.h" #include "ObjectAccessor.h" #include "Pet.h" +#include "MapManager.h" void WorldSession::SendNameQueryOpcode(Player *p) { @@ -185,7 +186,6 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data ) data << (uint32)ci->type; data << (uint32)ci->family; // family wdbFeild9 data << (uint32)ci->rank; // rank wdbFeild10 - data << (uint32)0; // unknown wdbFeild11 data << (uint32)ci->PetSpellDataId; // Id from CreatureSpellData.dbc wdbField12 data << (uint32)ci->Modelid1; // Modelid1 data << (uint32)ci->Modelid2; // Modelid2 @@ -276,20 +276,43 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) Corpse *corpse = GetPlayer()->GetCorpse(); - uint8 found = 1; if(!corpse) - found = 0; + { + WorldPacket data(MSG_CORPSE_QUERY, 1); + data << uint8(0); // corpse not found + SendPacket(&data); + return; + } - WorldPacket data(MSG_CORPSE_QUERY, (1+found*(5*4))); - data << uint8(found); - if(found) + int32 mapid = corpse->GetMapId(); + float x = corpse->GetPositionX(); + float y = corpse->GetPositionY(); + float z = corpse->GetPositionZ(); + int32 corpsemapid = _player->GetMapId(); + + if(Map *map = MapManager::Instance().FindMap(corpse->GetMapId(), corpse->GetInstanceId())) { - data << corpse->GetMapId(); - data << corpse->GetPositionX(); - data << corpse->GetPositionY(); - data << corpse->GetPositionZ(); - data << _player->GetMapId(); + if(map->IsDungeon()) + { + if(!map->GetEntrancePos(mapid, x, y)) + return; + + Map *entrance_map = MapManager::Instance().GetMap(mapid, _player); + if(!entrance_map) + return; + + z = entrance_map->GetHeight(x, y, MAX_HEIGHT); + corpsemapid = corpse->GetMapId(); + } } + + WorldPacket data(MSG_CORPSE_QUERY, 1+(5*4)); + data << uint8(1); // corpse found + data << int32(mapid); + data << float(x); + data << float(y); + data << float(z); + data << int32(corpsemapid); SendPacket(&data); } diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp index 4dd202bc344..d07b56c6157 100644 --- a/src/game/QuestDef.cpp +++ b/src/game/QuestDef.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,88 +44,90 @@ Quest::Quest(Field * questRecord) QuestFlags = questRecord[17].GetUInt16(); uint32 SpecialFlags = questRecord[18].GetUInt16(); CharTitleId = questRecord[19].GetUInt32(); - PrevQuestId = questRecord[20].GetInt32(); - NextQuestId = questRecord[21].GetInt32(); - ExclusiveGroup = questRecord[22].GetInt32(); - NextQuestInChain = questRecord[23].GetUInt32(); - SrcItemId = questRecord[24].GetUInt32(); - SrcItemCount = questRecord[25].GetUInt32(); - SrcSpell = questRecord[26].GetUInt32(); - Title = questRecord[27].GetCppString(); - Details = questRecord[28].GetCppString(); - Objectives = questRecord[29].GetCppString(); - OfferRewardText = questRecord[30].GetCppString(); - RequestItemsText = questRecord[31].GetCppString(); - EndText = questRecord[32].GetCppString(); + PlayersSlain = questRecord[20].GetUInt32(); + BonusTalents = questRecord[21].GetUInt32(); + PrevQuestId = questRecord[22].GetInt32(); + NextQuestId = questRecord[23].GetInt32(); + ExclusiveGroup = questRecord[24].GetInt32(); + NextQuestInChain = questRecord[25].GetUInt32(); + SrcItemId = questRecord[26].GetUInt32(); + SrcItemCount = questRecord[27].GetUInt32(); + SrcSpell = questRecord[28].GetUInt32(); + Title = questRecord[29].GetCppString(); + Details = questRecord[30].GetCppString(); + Objectives = questRecord[31].GetCppString(); + OfferRewardText = questRecord[32].GetCppString(); + RequestItemsText = questRecord[33].GetCppString(); + EndText = questRecord[34].GetCppString(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ObjectiveText[i] = questRecord[33+i].GetCppString(); + ObjectiveText[i] = questRecord[35+i].GetCppString(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqItemId[i] = questRecord[37+i].GetUInt32(); + ReqItemId[i] = questRecord[39+i].GetUInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqItemCount[i] = questRecord[41+i].GetUInt32(); + ReqItemCount[i] = questRecord[43+i].GetUInt32(); for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) - ReqSourceId[i] = questRecord[45+i].GetUInt32(); + ReqSourceId[i] = questRecord[47+i].GetUInt32(); for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) - ReqSourceCount[i] = questRecord[49+i].GetUInt32(); + ReqSourceCount[i] = questRecord[51+i].GetUInt32(); for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) - ReqSourceRef[i] = questRecord[53+i].GetUInt32(); + ReqSourceRef[i] = questRecord[55+i].GetUInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqCreatureOrGOId[i] = questRecord[57+i].GetInt32(); + ReqCreatureOrGOId[i] = questRecord[59+i].GetInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqCreatureOrGOCount[i] = questRecord[61+i].GetUInt32(); + ReqCreatureOrGOCount[i] = questRecord[63+i].GetUInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqSpell[i] = questRecord[65+i].GetUInt32(); + ReqSpell[i] = questRecord[67+i].GetUInt32(); for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) - RewChoiceItemId[i] = questRecord[69+i].GetUInt32(); + RewChoiceItemId[i] = questRecord[71+i].GetUInt32(); for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) - RewChoiceItemCount[i] = questRecord[75+i].GetUInt32(); + RewChoiceItemCount[i] = questRecord[78+i].GetUInt32(); for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) - RewItemId[i] = questRecord[81+i].GetUInt32(); + RewItemId[i] = questRecord[85+i].GetUInt32(); for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) - RewItemCount[i] = questRecord[85+i].GetUInt32(); + RewItemCount[i] = questRecord[89+i].GetUInt32(); for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) - RewRepFaction[i] = questRecord[89+i].GetUInt32(); + RewRepFaction[i] = questRecord[93+i].GetUInt32(); for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) - RewRepValue[i] = questRecord[94+i].GetInt32(); - - RewHonorableKills = questRecord[99].GetUInt32(); - RewOrReqMoney = questRecord[100].GetInt32(); - RewMoneyMaxLevel = questRecord[101].GetUInt32(); - RewSpell = questRecord[102].GetUInt32(); - RewSpellCast = questRecord[103].GetUInt32(); - RewMailTemplateId = questRecord[104].GetUInt32(); - RewMailDelaySecs = questRecord[105].GetUInt32(); - PointMapId = questRecord[106].GetUInt32(); - PointX = questRecord[107].GetFloat(); - PointY = questRecord[108].GetFloat(); - PointOpt = questRecord[109].GetUInt32(); + RewRepValue[i] = questRecord[98+i].GetInt32(); + + RewHonorableKills = questRecord[103].GetUInt32(); + RewOrReqMoney = questRecord[104].GetInt32(); + RewMoneyMaxLevel = questRecord[105].GetUInt32(); + RewSpell = questRecord[106].GetUInt32(); + RewSpellCast = questRecord[107].GetUInt32(); + RewMailTemplateId = questRecord[108].GetUInt32(); + RewMailDelaySecs = questRecord[109].GetUInt32(); + PointMapId = questRecord[110].GetUInt32(); + PointX = questRecord[111].GetFloat(); + PointY = questRecord[112].GetFloat(); + PointOpt = questRecord[113].GetUInt32(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - DetailsEmote[i] = questRecord[110+i].GetUInt32(); + DetailsEmote[i] = questRecord[114+i].GetUInt32(); - IncompleteEmote = questRecord[114].GetUInt32(); - CompleteEmote = questRecord[115].GetUInt32(); + IncompleteEmote = questRecord[118].GetUInt32(); + CompleteEmote = questRecord[119].GetUInt32(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - OfferRewardEmote[i] = questRecord[116+i].GetInt32(); + OfferRewardEmote[i] = questRecord[120+i].GetInt32(); - QuestStartScript = questRecord[120].GetUInt32(); - QuestCompleteScript = questRecord[121].GetUInt32(); + QuestStartScript = questRecord[124].GetUInt32(); + QuestCompleteScript = questRecord[125].GetUInt32(); QuestFlags |= SpecialFlags << 16; @@ -164,18 +166,20 @@ uint32 Quest::XPValue( Player *pPlayer ) const uint32 pLevel = pPlayer->getLevel(); uint32 qLevel = QuestLevel; float fullxp = 0; - if (qLevel >= 65) + if (qLevel >= 15) fullxp = RewMoneyMaxLevel / 6.0f; - else if (qLevel == 64) + else if (qLevel == 14) fullxp = RewMoneyMaxLevel / 4.8f; - else if (qLevel == 63) - fullxp = RewMoneyMaxLevel / 3.6f; - else if (qLevel == 62) + else if (qLevel == 13) + fullxp = RewMoneyMaxLevel / 3.666f; + else if (qLevel == 12) fullxp = RewMoneyMaxLevel / 2.4f; - else if (qLevel == 61) + else if (qLevel == 11) fullxp = RewMoneyMaxLevel / 1.2f; - else if (qLevel > 0 && qLevel <= 60) + else if (qLevel >= 1 && qLevel <= 10) fullxp = RewMoneyMaxLevel / 0.6f; + else if (qLevel == 0) + fullxp = RewMoneyMaxLevel; if( pLevel <= qLevel + 5 ) return (uint32)fullxp; diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h index 52f58c2c87e..3b5e7b1a3d9 100644 --- a/src/game/QuestDef.h +++ b/src/game/QuestDef.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,7 +35,7 @@ class ObjectMgr; #define QUEST_OBJECTIVES_COUNT 4 #define QUEST_SOURCE_ITEM_IDS_COUNT 4 -#define QUEST_REWARD_CHOICES_COUNT 6 +#define QUEST_REWARD_CHOICES_COUNT 7 #define QUEST_REWARDS_COUNT 4 #define QUEST_DEPLINK_COUNT 10 #define QUEST_REPUTATIONS_COUNT 5 @@ -44,30 +44,33 @@ class ObjectMgr; enum QuestFailedReasons { INVALIDREASON_DONT_HAVE_REQ = 0, - INVALIDREASON_QUEST_FAILED_LOW_LEVEL = 1, //You are not high enough level for that quest. - INVALIDREASON_QUEST_FAILED_WRONG_RACE = 6, //That quest is not available to your race. - INVALIDREASON_QUEST_ALREADY_DONE = 7, //You have completed that quest. - INVALIDREASON_QUEST_ONLY_ONE_TIMED = 12, //You can only be on one timed quest at a time. - INVALIDREASON_QUEST_ALREADY_ON = 13, //You are already on that quest - INVALIDREASON_QUEST_FAILED_EXPANSION = 16, //This quest requires an expansion enabled account. - INVALIDREASON_QUEST_ALREADY_ON2 = 18, //You are already on that quest - INVALIDREASON_QUEST_FAILED_MISSING_ITEMS = 21, //You don't have the required items with you. Check storage. - INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY = 23, //You don't have enough money for that quest. - INVALIDREASON_DAILY_QUESTS_REMAINING = 26, //You have already completed 10 daily quests today - INVALIDREASON_QUEST_FAILED_CAIS = 27, //You cannot complete quests once you have reached tired time + INVALIDREASON_QUEST_FAILED_LOW_LEVEL = 1, // You are not high enough level for that quest. + INVALIDREASON_QUEST_FAILED_WRONG_RACE = 6, // That quest is not available to your race. + INVALIDREASON_QUEST_ALREADY_DONE = 7, // You have completed that quest. + INVALIDREASON_QUEST_ONLY_ONE_TIMED = 12, // You can only be on one timed quest at a time. + INVALIDREASON_QUEST_ALREADY_ON = 13, // You are already on that quest. + INVALIDREASON_QUEST_FAILED_EXPANSION = 16, // This quest requires an expansion enabled account. + INVALIDREASON_QUEST_ALREADY_ON2 = 18, // You are already on that quest. + INVALIDREASON_QUEST_FAILED_MISSING_ITEMS = 21, // You don't have the required items with you. Check storage. + INVALIDREASON_QUEST_FAILED_NOT_ENOUGH_MONEY = 23, // You don't have enough money for that quest. + INVALIDREASON_DAILY_QUESTS_REMAINING = 26, // You have already completed 25 daily quests today. + INVALIDREASON_QUEST_FAILED_CAIS = 27, // You cannot complete quests once you have reached tired time. + INVALIDREASON_DAILY_QUEST_COMPLETED_TODAY = 29 // You have completed that daily quest today. }; enum QuestShareMessages { - QUEST_PARTY_MSG_SHARING_QUEST = 0, - QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1, - QUEST_PARTY_MSG_ACCEPT_QUEST = 2, - QUEST_PARTY_MSG_REFUSE_QUEST = 3, - QUEST_PARTY_MSG_TOO_FAR = 4, - QUEST_PARTY_MSG_BUSY = 5, - QUEST_PARTY_MSG_LOG_FULL = 6, - QUEST_PARTY_MSG_HAVE_QUEST = 7, - QUEST_PARTY_MSG_FINISH_QUEST = 8, + QUEST_PARTY_MSG_SHARING_QUEST = 0, + QUEST_PARTY_MSG_CANT_TAKE_QUEST = 1, + QUEST_PARTY_MSG_ACCEPT_QUEST = 2, + QUEST_PARTY_MSG_DECLINE_QUEST = 3, + QUEST_PARTY_MSG_BUSY = 4, + QUEST_PARTY_MSG_LOG_FULL = 5, + QUEST_PARTY_MSG_HAVE_QUEST = 6, + QUEST_PARTY_MSG_FINISH_QUEST = 7, + QUEST_PARTY_MSG_CANT_BE_SHARED_TODAY = 8, + QUEST_PARTY_MSG_SHARING_TIMER_EXPIRED = 9, + QUEST_PARTY_MSG_NOT_IN_PARTY = 10 }; enum __QuestTradeSkill @@ -190,6 +193,8 @@ class Quest int32 GetExclusiveGroup() const { return ExclusiveGroup; } uint32 GetNextQuestInChain() const { return NextQuestInChain; } uint32 GetCharTitleId() const { return CharTitleId; } + uint32 GetPlayersSlain() const { return PlayersSlain; } + uint32 GetBonusTalents() const { return BonusTalents; } uint32 GetSrcItemId() const { return SrcItemId; } uint32 GetSrcItemCount() const { return SrcItemCount; } uint32 GetSrcSpell() const { return SrcSpell; } @@ -277,6 +282,8 @@ class Quest uint32 LimitTime; uint32 QuestFlags; uint32 CharTitleId; + uint32 PlayersSlain; + uint32 BonusTalents; int32 PrevQuestId; int32 NextQuestId; int32 ExclusiveGroup; diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index abb285e6dbb..98d4972c406 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -180,7 +180,7 @@ void WorldSession::HandleQuestgiverAcceptQuestOpcode( WorldPacket & recv_data ) bool destroyItem = true; for(int i = 0; i < QUEST_OBJECTIVES_COUNT; i++) { - if ((qInfo->ReqItemId[i] == ((Item*)pObject)->GetEntry()) && (((Item*)pObject)->GetProto()->MaxCount != 0)) + if ((qInfo->ReqItemId[i] == ((Item*)pObject)->GetEntry()) && (((Item*)pObject)->GetProto()->MaxCount > 0)) { destroyItem = false; break; @@ -451,12 +451,6 @@ void WorldSession::HandleQuestPushToParty(WorldPacket& recvPacket) _player->SendPushToPartyResponse(pPlayer, QUEST_PARTY_MSG_SHARING_QUEST); - if( _player->GetDistance( pPlayer ) > 10 ) - { - _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_TOO_FAR ); - continue; - } - if( !pPlayer->SatisfyQuestStatus( pQuest, false ) ) { _player->SendPushToPartyResponse( pPlayer, QUEST_PARTY_MSG_HAVE_QUEST ); diff --git a/src/game/RandomMovementGenerator.cpp b/src/game/RandomMovementGenerator.cpp index 0679d1381db..0e85c1911a5 100644 --- a/src/game/RandomMovementGenerator.cpp +++ b/src/game/RandomMovementGenerator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/RandomMovementGenerator.h b/src/game/RandomMovementGenerator.h index ed34b96f608..e2d2a5005fb 100644 --- a/src/game/RandomMovementGenerator.h +++ b/src/game/RandomMovementGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp index 29b07f60b00..02799431991 100644 --- a/src/game/ReactorAI.cpp +++ b/src/game/ReactorAI.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ReactorAI.h b/src/game/ReactorAI.h index cea1e8dcdb5..e549bfc7243 100644 --- a/src/game/ReactorAI.h +++ b/src/game/ReactorAI.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ScriptCalls.cpp b/src/game/ScriptCalls.cpp index 4bd305917b2..78d63c460ce 100644 --- a/src/game/ScriptCalls.cpp +++ b/src/game/ScriptCalls.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -86,7 +86,8 @@ bool LoadScriptingModule(char const* libName) return false; } - printf("Scripts Library %s was successfully loaded.\n",name.c_str()); + sLog.outString(); + sLog.outString( ">>> Scripts Library %s was successfully loaded.\n", name.c_str() ); //heh we are still there :P we have a valid library //we reload script diff --git a/src/game/ScriptCalls.h b/src/game/ScriptCalls.h index 52b2f27f218..216a694936f 100644 --- a/src/game/ScriptCalls.h +++ b/src/game/ScriptCalls.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index e0e3a5ba077..aa9d4fe153f 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,9 @@ #include "Platform/Define.h" #include <cassert> +#define MaNGOS Trinity +#define GetMangosString GetTrinityString + enum Gender { GENDER_MALE = 0, @@ -88,7 +91,8 @@ enum Classes #define CLASSMASK_ALL_PLAYABLE \ ((1<<(CLASS_WARRIOR-1))|(1<<(CLASS_PALADIN-1))|(1<<(CLASS_HUNTER-1))| \ (1<<(CLASS_ROGUE-1)) |(1<<(CLASS_PRIEST-1)) |(1<<(CLASS_SHAMAN-1))| \ - (1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) ) + (1<<(CLASS_MAGE-1)) |(1<<(CLASS_WARLOCK-1))|(1<<(CLASS_DRUID-1)) | \ + (1<<(CLASS_DEATH_KNIGHT-1)) ) #define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1))) @@ -134,11 +138,12 @@ enum Powers POWER_FOCUS = 2, POWER_ENERGY = 3, POWER_HAPPINESS = 4, - POWER_RUNES = 5, + POWER_RUNE = 5, + POWER_RUNIC_POWER = 6, POWER_HEALTH = 0xFFFFFFFE // (-2 as signed value) }; -#define MAX_POWERS 5 // not count POWER_RUNES for now +#define MAX_POWERS 7 enum SpellSchools { @@ -199,10 +204,11 @@ enum ItemQualities ITEM_QUALITY_RARE = 3, //BLUE ITEM_QUALITY_EPIC = 4, //PURPLE ITEM_QUALITY_LEGENDARY = 5, //ORANGE - ITEM_QUALITY_ARTIFACT = 6 //LIGHT YELLOW + ITEM_QUALITY_ARTIFACT = 6, //LIGHT YELLOW + ITEM_QUALITY_HEIRLOOM = 7 }; -#define MAX_ITEM_QUALITY 7 +#define MAX_ITEM_QUALITY 8 enum SpellCategory { @@ -217,7 +223,7 @@ enum SpellCategory #define SPELL_ATTR_UNK0 0x00000001 // 0 #define SPELL_ATTR_RANGED 0x00000002 // 1 All ranged abilities have this flag #define SPELL_ATTR_ON_NEXT_SWING_1 0x00000004 // 2 on next swing -#define SPELL_ATTR_UNK3 0x00000008 // 3 not set in 2.4.2 +#define SPELL_ATTR_UNK3 0x00000008 // 3 not set in 3.0.3 #define SPELL_ATTR_UNK4 0x00000010 // 4 #define SPELL_ATTR_UNK5 0x00000020 // 5 trade spells? #define SPELL_ATTR_PASSIVE 0x00000040 // 6 Passive spell @@ -257,7 +263,7 @@ enum SpellCategory #define SPELL_ATTR_EX_NEGATIVE 0x00000080 // 7 #define SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET 0x00000100 // 8 Spell req target not to be in combat state #define SPELL_ATTR_EX_UNK9 0x00000200 // 9 -#define SPELL_ATTR_EX_UNK10 0x00000400 // 10 +#define SPELL_ATTR_EX_NO_INITIAL_AGGRO 0x00000400 // 10 no generates threat on cast 100% #define SPELL_ATTR_EX_UNK11 0x00000800 // 11 #define SPELL_ATTR_EX_UNK12 0x00001000 // 12 #define SPELL_ATTR_EX_UNK13 0x00002000 // 13 @@ -272,7 +278,7 @@ enum SpellCategory #define SPELL_ATTR_EX_REQ_COMBO_POINTS2 0x00400000 // 22 Req combo points on target #define SPELL_ATTR_EX_UNK23 0x00800000 // 23 #define SPELL_ATTR_EX_UNK24 0x01000000 // 24 Req fishing pole?? -#define SPELL_ATTR_EX_UNK25 0x02000000 // 25 not set in 2.4.2 +#define SPELL_ATTR_EX_UNK25 0x02000000 // 25 #define SPELL_ATTR_EX_UNK26 0x04000000 // 26 #define SPELL_ATTR_EX_UNK27 0x08000000 // 27 #define SPELL_ATTR_EX_UNK28 0x10000000 // 28 @@ -282,20 +288,20 @@ enum SpellCategory #define SPELL_ATTR_EX2_UNK0 0x00000001 // 0 #define SPELL_ATTR_EX2_UNK1 0x00000002 // 1 -#define SPELL_ATTR_EX2_UNK2 0x00000004 // 2 boss spells? +#define SPELL_ATTR_EX2_CANT_REFLECTED 0x00000004 // 2 ? used for detect can or not spell reflected #define SPELL_ATTR_EX2_UNK3 0x00000008 // 3 #define SPELL_ATTR_EX2_UNK4 0x00000010 // 4 -#define SPELL_ATTR_EX2_UNK5 0x00000020 // 5 +#define SPELL_ATTR_EX2_AUTOREPEAT_FLAG 0x00000020 // 5 #define SPELL_ATTR_EX2_UNK6 0x00000040 // 6 #define SPELL_ATTR_EX2_UNK7 0x00000080 // 7 -#define SPELL_ATTR_EX2_UNK8 0x00000100 // 8 not set in 2.4.2 +#define SPELL_ATTR_EX2_UNK8 0x00000100 // 8 not set in 3.0.3 #define SPELL_ATTR_EX2_UNK9 0x00000200 // 9 #define SPELL_ATTR_EX2_UNK10 0x00000400 // 10 #define SPELL_ATTR_EX2_HEALTH_FUNNEL 0x00000800 // 11 #define SPELL_ATTR_EX2_UNK12 0x00001000 // 12 #define SPELL_ATTR_EX2_UNK13 0x00002000 // 13 #define SPELL_ATTR_EX2_UNK14 0x00004000 // 14 -#define SPELL_ATTR_EX2_UNK15 0x00008000 // 15 not set in 2.4.2 +#define SPELL_ATTR_EX2_UNK15 0x00008000 // 15 not set in 3.0.3 #define SPELL_ATTR_EX2_TAME_BEAST 0x00010000 // 16 #define SPELL_ATTR_EX2_NOT_RESET_AUTOSHOT 0x00020000 // 17 Hunters Shot and Stings only have this flag #define SPELL_ATTR_EX2_UNK18 0x00040000 // 18 Only Revive pet - possible req dead pet @@ -308,7 +314,7 @@ enum SpellCategory #define SPELL_ATTR_EX2_UNK25 0x02000000 // 25 #define SPELL_ATTR_EX2_UNK26 0x04000000 // 26 unaffected by school immunity #define SPELL_ATTR_EX2_UNK27 0x08000000 // 27 -#define SPELL_ATTR_EX2_UNK28 0x10000000 // 28 +#define SPELL_ATTR_EX2_UNK28 0x10000000 // 28 no breaks stealth if it fails?? #define SPELL_ATTR_EX2_CANT_CRIT 0x20000000 // 29 Spell can't crit #define SPELL_ATTR_EX2_UNK30 0x40000000 // 30 #define SPELL_ATTR_EX2_FOOD 0x80000000 // 31 food, well-fed, and a few others @@ -329,8 +335,8 @@ enum SpellCategory #define SPELL_ATTR_EX3_UNK13 0x00002000 // 13 #define SPELL_ATTR_EX3_UNK14 0x00004000 // 14 "Honorless Target" only this spells have this flag #define SPELL_ATTR_EX3_UNK15 0x00008000 // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag -#define SPELL_ATTR_EX3_UNK16 0x00010000 // 16 -#define SPELL_ATTR_EX3_NO_INITIAL_AGGRO 0x00020000 // 17 no initial aggro +#define SPELL_ATTR_EX3_UNK16 0x00010000 // 16 no triggers effects that trigger on casting a spell?? +#define SPELL_ATTR_EX3_UNK17 0x00020000 // 17 no triggers effects that trigger on casting a spell?? #define SPELL_ATTR_EX3_UNK18 0x00040000 // 18 #define SPELL_ATTR_EX3_UNK19 0x00080000 // 19 #define SPELL_ATTR_EX3_DEATH_PERSISTENT 0x00100000 // 20 Death persistent spells @@ -338,7 +344,7 @@ enum SpellCategory #define SPELL_ATTR_EX3_REQ_WAND 0x00400000 // 22 Req wand #define SPELL_ATTR_EX3_UNK23 0x00800000 // 23 #define SPELL_ATTR_EX3_REQ_OFFHAND 0x01000000 // 24 Req offhand weapon -#define SPELL_ATTR_EX3_UNK25 0x02000000 // 25 +#define SPELL_ATTR_EX3_UNK25 0x02000000 // 25 no cause spell pushback ? #define SPELL_ATTR_EX3_UNK26 0x04000000 // 26 #define SPELL_ATTR_EX3_UNK27 0x08000000 // 27 #define SPELL_ATTR_EX3_UNK28 0x10000000 // 28 @@ -350,7 +356,7 @@ enum SpellCategory #define SPELL_ATTR_EX4_UNK1 0x00000002 // 1 proc on finishing move? #define SPELL_ATTR_EX4_UNK2 0x00000004 // 2 #define SPELL_ATTR_EX4_UNK3 0x00000008 // 3 -#define SPELL_ATTR_EX4_UNK4 0x00000010 // 4 +#define SPELL_ATTR_EX4_UNK4 0x00000010 // 4 This will no longer cause guards to attack on use?? #define SPELL_ATTR_EX4_UNK5 0x00000020 // 5 #define SPELL_ATTR_EX4_UNK6 0x00000040 // 6 #define SPELL_ATTR_EX4_UNK7 0x00000080 // 7 @@ -388,7 +394,7 @@ enum SpellCategory #define SPELL_ATTR_EX5_UNK6 0x00000040 // 6 #define SPELL_ATTR_EX5_UNK7 0x00000080 // 7 #define SPELL_ATTR_EX5_UNK8 0x00000100 // 8 -#define SPELL_ATTR_EX5_UNK9 0x00000200 // 9 +#define SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY 0x00000200 // 9 begin periodic tick at aura apply #define SPELL_ATTR_EX5_UNK10 0x00000400 // 10 #define SPELL_ATTR_EX5_UNK11 0x00000800 // 11 #define SPELL_ATTR_EX5_UNK12 0x00001000 // 12 @@ -413,37 +419,39 @@ enum SpellCategory #define SPELL_ATTR_EX5_UNK31 0x80000000 // 31 Forces all nearby enemies to focus attacks caster #define SPELL_ATTR_EX6_UNK0 0x00000001 // 0 Only Move spell have this flag -#define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK1 0x00000002 // 1 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK2 0x00000004 // 2 #define SPELL_ATTR_EX6_UNK3 0x00000008 // 3 -#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK4 0x00000010 // 4 #define SPELL_ATTR_EX6_UNK5 0x00000020 // 5 #define SPELL_ATTR_EX6_UNK6 0x00000040 // 6 #define SPELL_ATTR_EX6_UNK7 0x00000080 // 7 #define SPELL_ATTR_EX6_UNK8 0x00000100 // 8 -#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK9 0x00000200 // 9 #define SPELL_ATTR_EX6_UNK10 0x00000400 // 10 #define SPELL_ATTR_EX6_UNK11 0x00000800 // 11 -#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK15 0x00008000 // 15 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK16 0x00010000 // 16 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK17 0x00020000 // 17 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK18 0x00040000 // 18 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK19 0x00080000 // 19 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK20 0x00100000 // 20 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK21 0x00200000 // 21 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK22 0x00400000 // 22 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK23 0x00800000 // 23 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK24 0x01000000 // 24 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK25 0x02000000 // 25 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 2.4.2 -#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 2.4.2 +#define SPELL_ATTR_EX6_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX6_UNK13 0x00002000 // 13 +#define SPELL_ATTR_EX6_UNK14 0x00004000 // 14 +#define SPELL_ATTR_EX6_UNK15 0x00008000 // 15 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK16 0x00010000 // 16 +#define SPELL_ATTR_EX6_UNK17 0x00020000 // 17 +#define SPELL_ATTR_EX6_UNK18 0x00040000 // 18 +#define SPELL_ATTR_EX6_UNK19 0x00080000 // 19 +#define SPELL_ATTR_EX6_UNK20 0x00100000 // 20 +#define SPELL_ATTR_EX6_UNK21 0x00200000 // 21 +#define SPELL_ATTR_EX6_UNK22 0x00400000 // 22 +#define SPELL_ATTR_EX6_UNK23 0x00800000 // 23 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK24 0x01000000 // 24 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK25 0x02000000 // 25 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 3.0.3 +#define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 3.0.3 + +#define MAX_GLYPH_SLOT_INDEX 5 enum SheathTypes { @@ -562,11 +570,11 @@ enum SpellEffects SPELL_EFFECT_DISPEL = 38, SPELL_EFFECT_LANGUAGE = 39, SPELL_EFFECT_DUAL_WIELD = 40, - SPELL_EFFECT_SUMMON_WILD = 41, - SPELL_EFFECT_SUMMON_GUARDIAN = 42, + SPELL_EFFECT_JUMP = 41, + SPELL_EFFECT_JUMP2 = 42, SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER= 43, SPELL_EFFECT_SKILL_STEP = 44, - SPELL_EFFECT_UNDEFINED_45 = 45, + SPELL_EFFECT_ADD_HONOR = 45, SPELL_EFFECT_SPAWN = 46, SPELL_EFFECT_TRADE_SKILL = 47, SPELL_EFFECT_STEALTH = 48, @@ -586,16 +594,16 @@ enum SpellEffects SPELL_EFFECT_POWER_BURN = 62, SPELL_EFFECT_THREAT = 63, SPELL_EFFECT_TRIGGER_SPELL = 64, - SPELL_EFFECT_HEALTH_FUNNEL = 65, - SPELL_EFFECT_POWER_FUNNEL = 66, + SPELL_EFFECT_APPLY_AREA_AURA_RAID = 65, + SPELL_EFFECT_CREATE_MANA_GEM = 66, SPELL_EFFECT_HEAL_MAX_HEALTH = 67, SPELL_EFFECT_INTERRUPT_CAST = 68, SPELL_EFFECT_DISTRACT = 69, SPELL_EFFECT_PULL = 70, SPELL_EFFECT_PICKPOCKET = 71, SPELL_EFFECT_ADD_FARSIGHT = 72, - SPELL_EFFECT_SUMMON_POSSESSED = 73, - SPELL_EFFECT_SUMMON_TOTEM = 74, + SPELL_EFFECT_UNTRAIN_TALENTS = 73, + SPELL_EFFECT_APPLY_GLYPH = 74, SPELL_EFFECT_HEAL_MECHANICAL = 75, SPELL_EFFECT_SUMMON_OBJECT_WILD = 76, SPELL_EFFECT_SCRIPT_EFFECT = 77, @@ -608,17 +616,17 @@ enum SpellEffects SPELL_EFFECT_STUCK = 84, SPELL_EFFECT_SUMMON_PLAYER = 85, SPELL_EFFECT_ACTIVATE_OBJECT = 86, - SPELL_EFFECT_SUMMON_TOTEM_SLOT1 = 87, - SPELL_EFFECT_SUMMON_TOTEM_SLOT2 = 88, - SPELL_EFFECT_SUMMON_TOTEM_SLOT3 = 89, - SPELL_EFFECT_SUMMON_TOTEM_SLOT4 = 90, + SPELL_EFFECT_WMO_DAMAGE = 87, + SPELL_EFFECT_WMO_REPAIR = 88, + SPELL_EFFECT_WMO_CHANGE = 89, + SPELL_EFFECT_KILL_CREDIT = 90, SPELL_EFFECT_THREAT_ALL = 91, SPELL_EFFECT_ENCHANT_HELD_ITEM = 92, SPELL_EFFECT_SUMMON_PHANTASM = 93, //unused SPELL_EFFECT_SELF_RESURRECT = 94, SPELL_EFFECT_SKINNING = 95, SPELL_EFFECT_CHARGE = 96, - SPELL_EFFECT_SUMMON_CRITTER = 97, + SPELL_EFFECT_97 = 97, SPELL_EFFECT_KNOCK_BACK = 98, SPELL_EFFECT_DISENCHANT = 99, SPELL_EFFECT_INEBRIATE = 100, @@ -633,7 +641,7 @@ enum SpellEffects SPELL_EFFECT_SUMMON_DEAD_PET = 109, SPELL_EFFECT_DESTROY_ALL_TOTEMS = 110, SPELL_EFFECT_DURABILITY_DAMAGE = 111, - SPELL_EFFECT_SUMMON_DEMON = 112, + SPELL_EFFECT_112 = 112, SPELL_EFFECT_RESURRECT_NEW = 113, SPELL_EFFECT_ATTACK_ME = 114, SPELL_EFFECT_DURABILITY_DAMAGE_PCT = 115, @@ -655,19 +663,19 @@ enum SpellEffects SPELL_EFFECT_131 = 131, SPELL_EFFECT_132 = 132, SPELL_EFFECT_UNLEARN_SPECIALIZATION = 133, - SPELL_EFFECT_KILL_CREDIT = 134, + SPELL_EFFECT_KILL_CREDIT2 = 134, SPELL_EFFECT_135 = 135, SPELL_EFFECT_HEAL_PCT = 136, SPELL_EFFECT_ENERGIZE_PCT = 137, SPELL_EFFECT_138 = 138, - SPELL_EFFECT_139 = 139, + SPELL_EFFECT_CLEAR_QUEST = 139, SPELL_EFFECT_FORCE_CAST = 140, SPELL_EFFECT_141 = 141, SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE = 142, SPELL_EFFECT_APPLY_AREA_AURA_OWNER = 143, SPELL_EFFECT_KNOCK_BACK_2 = 144, SPELL_EFFECT_145 = 145, - SPELL_EFFECT_146 = 146, + SPELL_EFFECT_ACTIVATE_RUNE = 146, SPELL_EFFECT_QUEST_FAIL = 147, SPELL_EFFECT_148 = 148, SPELL_EFFECT_149 = 149, @@ -675,7 +683,13 @@ enum SpellEffects SPELL_EFFECT_TRIGGER_SPELL_2 = 151, SPELL_EFFECT_152 = 152, SPELL_EFFECT_153 = 153, - TOTAL_SPELL_EFFECTS = 154 + SPELL_EFFECT_154 = 154, + SPELL_EFFECT_TITAN_GRIP = 155, + SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC = 156, + SPELL_EFFECT_CREATE_ITEM_2 = 157, + SPELL_EFFECT_MILLING = 158, + SPELL_EFFECT_ALLOW_RENAME_PET = 159, + TOTAL_SPELL_EFFECTS = 160 }; // Spell aura states @@ -685,25 +699,28 @@ enum AuraState AURA_STATE_DEFENSE = 1, // C | AURA_STATE_HEALTHLESS_20_PERCENT = 2, // CcT | AURA_STATE_BERSERKING = 3, // C T | - //AURA_STATE_UNKNOWN4 = 4, // c t| some limitation to charge spells (?) and target test spells + AURA_STATE_FROZEN = 4, // c t| frozen target AURA_STATE_JUDGEMENT = 5, // C | //AURA_STATE_UNKNOWN6 = 6, // | not used AURA_STATE_HUNTER_PARRY = 7, // C | AURA_STATE_ROGUE_ATTACK_FROM_STEALTH = 7, // C | FIX ME: not implemented yet! - //AURA_STATE_UNKNOWN7c = 7, // c | random/focused bursts spells (?) + //AURA_STATE_UNKNOWN7 = 7, // c | random/focused bursts spells (?) //AURA_STATE_UNKNOWN8 = 8, // | not used //AURA_STATE_UNKNOWN9 = 9, // | not used AURA_STATE_WARRIOR_VICTORY_RUSH = 10, // C | warrior victory rush - AURA_STATE_HUNTER_CRIT_STRIKE = 10, // C | hunter crit strike - AURA_STATE_CRIT = 11, // C | + //AURA_STATE_UNKNOWN11 = 11, // t| AURA_STATE_FAERIE_FIRE = 12, // c t| AURA_STATE_HEALTHLESS_35_PERCENT = 13, // C T | AURA_STATE_IMMOLATE = 14, // T | AURA_STATE_SWIFTMEND = 15, // T | AURA_STATE_DEADLY_POISON = 16, // T | - AURA_STATE_FORBEARANCE = 17, // c t| - AURA_STATE_WEAKENED_SOUL = 18, // t| - AURA_STATE_HYPOTHERMIA = 19 // c | + AURA_STATE_ENRAGE = 17, // C | + //AURA_STATE_UNKNOWN18 = 18, // C t| + //AURA_STATE_UNKNOWN19 = 19, // | not used + //AURA_STATE_UNKNOWN20 = 20, // c | only (45317 Suicide) + //AURA_STATE_UNKNOWN21 = 21, // | not used + //AURA_STATE_UNKNOWN22 = 22, // C | not implemented yet (Requires Evasive Charges to use) + AURA_STATE_HEALTH_ABOVE_75_PERCENT = 23, // C | }; // Spell mechanics @@ -711,11 +728,11 @@ enum Mechanics { MECHANIC_NONE = 0, MECHANIC_CHARM = 1, - MECHANIC_CONFUSED = 2, + MECHANIC_DISORIENTED = 2, MECHANIC_DISARM = 3, MECHANIC_DISTRACT = 4, MECHANIC_FEAR = 5, - MECHANIC_FUMBLE = 6, + MECHANIC_GRIP = 6, MECHANIC_ROOT = 7, MECHANIC_PACIFY = 8, //0 spells use this mechanic MECHANIC_SILENCE = 9, @@ -731,7 +748,7 @@ enum Mechanics MECHANIC_SHIELD = 19, MECHANIC_SHACKLE = 20, MECHANIC_MOUNT = 21, - MECHANIC_PERSUADE = 22, //0 spells use this mechanic + MECHANIC_INFECTED = 22, MECHANIC_TURN = 23, MECHANIC_HORROR = 24, MECHANIC_INVULNERABILITY = 25, @@ -739,12 +756,13 @@ enum Mechanics MECHANIC_DAZE = 27, MECHANIC_DISCOVERY = 28, MECHANIC_IMMUNE_SHIELD = 29, // Divine (Blessing) Shield/Protection and Ice Block - MECHANIC_SAPPED = 30 + MECHANIC_SAPPED = 30, + MECHANIC_ENRAGED = 31 }; // Used for spell 42292 Immune Movement Impairment and Loss of Control (0x49967da6) #define IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK ( \ - (1<<MECHANIC_CHARM )|(1<<MECHANIC_CONFUSED )|(1<<MECHANIC_FEAR )| \ + (1<<MECHANIC_CHARM )|(1<<MECHANIC_DISORIENTED )|(1<<MECHANIC_FEAR )| \ (1<<MECHANIC_ROOT )|(1<<MECHANIC_PACIFY )|(1<<MECHANIC_SLEEP )| \ (1<<MECHANIC_SNARE )|(1<<MECHANIC_STUN )|(1<<MECHANIC_FREEZE)| \ (1<<MECHANIC_KNOCKOUT)|(1<<MECHANIC_POLYMORPH)|(1<<MECHANIC_BANISH)| \ @@ -764,7 +782,8 @@ enum DispelType DISPEL_ALL = 7, DISPEL_SPE_NPC_ONLY = 8, DISPEL_ENRAGE = 9, - DISPEL_ZG_TICKET = 10 + DISPEL_ZG_TICKET = 10, + DESPEL_OLD_UNUSED = 11 }; #define DISPEL_ALL_MASK ( (1<<DISPEL_MAGIC) | (1<<DISPEL_CURSE) | (1<<DISPEL_DISEASE) | (1<<DISPEL_POISON) ) @@ -790,10 +809,9 @@ enum Targets { TARGET_SELF = 1, TARGET_UNIT_CASTER = 1, - TARGET_RANDOM_ENEMY_CHAIN_IN_AREA = 2, // only one spell has that, but regardless, it's a target type after all - //TARGET_UNIT_NEARBY_ENEMY - TARGET_UNIT_SINGLE_UNKNOWN = 3, - TARGET_UNIT_NEARBY_ALLY = 4, + TARGET_UNIT_NEARBY_ENEMY = 2, + TARGET_UNIT_NEARBY_ALLY = 3, + TARGET_UNIT_NEARBY_ALLY_UNK = 4, TARGET_PET = 5, TARGET_UNIT_PET = 5, TARGET_CHAIN_DAMAGE = 6, @@ -816,7 +834,6 @@ enum Targets TARGET_UNIT_PARTY_CASTER = 20, TARGET_SINGLE_FRIEND = 21, TARGET_UNIT_TARGET_ALLY = 21, - TARGET_ALL_AROUND_CASTER = 22, // used only in TargetA, target selection dependent from TargetB TARGET_DEST_CASTER = 22, TARGET_GAMEOBJECT = 23, //TARGET_OBJECT_OPEN @@ -986,9 +1003,10 @@ enum GameobjectTypes GAMEOBJECT_TYPE_BARBER_CHAIR = 32, GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING = 33, GAMEOBJECT_TYPE_GUILD_BANK = 34, + GAMEOBJECT_TYPE_TRAPDOOR = 35 }; -#define MAX_GAMEOBJECT_TYPE 35 // sending to client this or greater value can crash client. +#define MAX_GAMEOBJECT_TYPE 36 // sending to client this or greater value can crash client. #define GAMEOBJECT_FISHINGNODE_ENTRY 35591 // Better to define it somewhere instead of hardcoding everywhere @@ -1555,7 +1573,9 @@ enum LockType LOCKTYPE_BLASTING = 16, LOCKTYPE_SLOW_OPEN = 17, LOCKTYPE_SLOW_CLOSE = 18, - LOCKTYPE_FISHING = 19 + LOCKTYPE_FISHING = 19, + LOCKTYPE_INSCRIPTION = 20, + LOCKTYPE_OPEN_FROM_VEHICLE = 21 }; enum TrainerType // this is important type for npcs! @@ -1568,6 +1588,7 @@ enum TrainerType // this is important #define MAX_TRAINER_TYPE 4 +// CreatureType.dbc enum CreatureType { CREATURE_TYPE_BEAST = 1, @@ -1587,6 +1608,7 @@ enum CreatureType uint32 const CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD = (1 << (CREATURE_TYPE_HUMANOID-1)) | (1 << (CREATURE_TYPE_UNDEAD-1)); +// CreatureFamily.dbc enum CreatureFamily { CREATURE_FAMILY_WOLF = 1, @@ -1598,6 +1620,7 @@ enum CreatureFamily CREATURE_FAMILY_CARRION_BIRD = 7, CREATURE_FAMILY_CRAB = 8, CREATURE_FAMILY_GORILLA = 9, + CREATURE_FAMILY_HORSE_CUSTOM = 10, // not exist in DBC but used for horse like beasts in DB CREATURE_FAMILY_RAPTOR = 11, CREATURE_FAMILY_TALLSTRIDER = 12, CREATURE_FAMILY_FELHUNTER = 15, @@ -1609,7 +1632,7 @@ enum CreatureFamily CREATURE_FAMILY_IMP = 23, CREATURE_FAMILY_BAT = 24, CREATURE_FAMILY_HYENA = 25, - CREATURE_FAMILY_OWL = 26, + CREATURE_FAMILY_BIRD_OF_PREY = 26, CREATURE_FAMILY_WIND_SERPENT = 27, CREATURE_FAMILY_REMOTE_CONTROL = 28, CREATURE_FAMILY_FELGUARD = 29, @@ -1619,14 +1642,24 @@ enum CreatureFamily CREATURE_FAMILY_SPOREBAT = 33, CREATURE_FAMILY_NETHER_RAY = 34, CREATURE_FAMILY_SERPENT = 35, - CREATURE_FAMILY_SEA_LION = 36 + CREATURE_FAMILY_MOTH = 37, + CREATURE_FAMILY_CHIMAERA = 38, + CREATURE_FAMILY_DEVILSAUR = 39, + CREATURE_FAMILY_GHOUL = 40, + CREATURE_FAMILY_SILITHID = 41, + CREATURE_FAMILY_WORM = 42, + CREATURE_FAMILY_RHINO = 43, + CREATURE_FAMILY_WASP = 44, + CREATURE_FAMILY_CORE_HOUND = 45, + CREATURE_FAMILY_SPIRIT_BEAST = 46 }; enum CreatureTypeFlags { - CREATURE_TYPEFLAGS_TAMEABLE = 0x0001, - CREATURE_TYPEFLAGS_HERBLOOT = 0x0100, - CREATURE_TYPEFLAGS_MININGLOOT = 0x0200 + CREATURE_TYPEFLAGS_TAMEABLE = 0x0001, + CREATURE_TYPEFLAGS_HERBLOOT = 0x0100, + CREATURE_TYPEFLAGS_MININGLOOT = 0x0200, + CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x8000 }; enum CreatureEliteType @@ -1651,6 +1684,8 @@ enum QuestTypes QUEST_TYPE_LEGENDARY = 83, QUEST_TYPE_ESCORT = 84, QUEST_TYPE_HEROIC = 85, + QUEST_TYPE_RAID_10 = 88, + QUEST_TYPE_RAID_25 = 89 }; // values based at QuestSort.dbc @@ -1661,7 +1696,7 @@ enum QuestSort QUEST_SORT_SEASONAL = 22, QUEST_SORT_UNDERCITY_OLD = 23, QUEST_SORT_HERBALISM = 24, - QUEST_SORT_SCARLET_MONASTERY_OLD= 25, + QUEST_SORT_BATTLEGROUNDS = 25, QUEST_SORT_ULDAMN_OLD = 41, QUEST_SORT_WARLOCK = 61, QUEST_SORT_WARRIOR = 81, @@ -1690,22 +1725,26 @@ enum QuestSort QUEST_SORT_REPUTATION = 367, QUEST_SORT_INVASION = 368, QUEST_SORT_MIDSUMMER = 369, - QUEST_SORT_BREWFEST = 370 + QUEST_SORT_BREWFEST = 370, + QUEST_SORT_INSCRIPTION = 371, + QUEST_SORT_DEATH_KNIGHT = 372, + QUEST_SORT_JEWELCRAFTING = 373 }; inline uint8 ClassByQuestSort(int32 QuestSort) { switch(QuestSort) { - case QUEST_SORT_WARLOCK: return CLASS_WARLOCK; - case QUEST_SORT_WARRIOR: return CLASS_WARRIOR; - case QUEST_SORT_SHAMAN: return CLASS_SHAMAN; - case QUEST_SORT_PALADIN: return CLASS_PALADIN; - case QUEST_SORT_MAGE: return CLASS_MAGE; - case QUEST_SORT_ROGUE: return CLASS_ROGUE; - case QUEST_SORT_HUNTER: return CLASS_HUNTER; - case QUEST_SORT_PRIEST: return CLASS_PRIEST; - case QUEST_SORT_DRUID: return CLASS_DRUID; + case QUEST_SORT_WARLOCK: return CLASS_WARLOCK; + case QUEST_SORT_WARRIOR: return CLASS_WARRIOR; + case QUEST_SORT_SHAMAN: return CLASS_SHAMAN; + case QUEST_SORT_PALADIN: return CLASS_PALADIN; + case QUEST_SORT_MAGE: return CLASS_MAGE; + case QUEST_SORT_ROGUE: return CLASS_ROGUE; + case QUEST_SORT_HUNTER: return CLASS_HUNTER; + case QUEST_SORT_PRIEST: return CLASS_PRIEST; + case QUEST_SORT_DRUID: return CLASS_DRUID; + case QUEST_SORT_DEATH_KNIGHT: return CLASS_DEATH_KNIGHT; } return 0; } @@ -1717,7 +1756,6 @@ enum SkillType SKILL_ARMS = 26, SKILL_COMBAT = 38, SKILL_SUBTLETY = 39, - SKILL_POISONS = 40, SKILL_SWORDS = 43, SKILL_AXES = 44, SKILL_BOWS = 45, @@ -1725,8 +1763,8 @@ enum SkillType SKILL_BEAST_MASTERY = 50, SKILL_SURVIVAL = 51, SKILL_MACES = 54, - SKILL_HOLY = 56, SKILL_2H_SWORDS = 55, + SKILL_HOLY = 56, SKILL_SHADOW = 78, SKILL_DEFENSE = 95, SKILL_LANG_COMMON = 98, @@ -1782,24 +1820,20 @@ enum SkillType SKILL_PET_BOAR = 211, SKILL_PET_CROCILISK = 212, SKILL_PET_CARRION_BIRD = 213, - SKILL_PET_GORILLA = 215, SKILL_PET_CRAB = 214, + SKILL_PET_GORILLA = 215, SKILL_PET_RAPTOR = 217, SKILL_PET_TALLSTRIDER = 218, SKILL_RACIAL_UNDED = 220, - SKILL_WEAPON_TALENTS = 222, SKILL_CROSSBOWS = 226, - SKILL_SPEARS = 227, SKILL_WANDS = 228, SKILL_POLEARMS = 229, SKILL_PET_SCORPID = 236, SKILL_ARCANE = 237, - SKILL_OPEN_LOCK = 242, SKILL_PET_TURTLE = 251, SKILL_ASSASSINATION = 253, SKILL_FURY = 256, SKILL_PROTECTION = 257, - SKILL_BEAST_TRAINING = 261, SKILL_PROTECTION2 = 267, SKILL_PET_TALENTS = 270, SKILL_PLATE_MAIL = 293, @@ -1829,7 +1863,7 @@ enum SkillType SKILL_LOCKPICKING = 633, SKILL_PET_BAT = 653, SKILL_PET_HYENA = 654, - SKILL_PET_OWL = 655, + SKILL_PET_BIRD_OF_PREY = 655, SKILL_PET_WIND_SERPENT = 656, SKILL_LANG_GUTTERSPEAK = 673, SKILL_RIDING_KODO = 713, @@ -1849,10 +1883,27 @@ enum SkillType SKILL_PET_WARP_STALKER = 766, SKILL_PET_RAVAGER = 767, SKILL_PET_SERPENT = 768, - SKILL_INTERNAL = 769 + SKILL_INTERNAL = 769, + SKILL_DK_BLOOD = 770, + SKILL_DK_FROST = 771, + SKILL_DK_UNHOLY = 772, + SKILL_INSCRIPTION = 773, + SKILL_PET_MOTH = 775, + SKILL_RUNEFORGING = 776, + SKILL_MOUNTS = 777, + SKILL_COMPANIONS = 778, + SKILL_PET_EXOTIC_CHIMAERA = 780, + SKILL_PET_EXOTIC_DEVILSAUR = 781, + SKILL_PET_GHOUL = 782, + SKILL_PET_EXOTIC_SILITHID = 783, + SKILL_PET_EXOTIC_WORM = 784, + SKILL_PET_WASP = 785, + SKILL_PET_EXOTIC_RHINO = 786, + SKILL_PET_EXOTIC_CORE_HOUND = 787, + SKILL_PET_EXOTIC_SPIRIT_BEAST = 788 }; -#define MAX_SKILL_TYPE 770 +#define MAX_SKILL_TYPE 789 inline uint32 SkillByQuestSort(int32 QuestSort) { @@ -1867,25 +1918,27 @@ inline uint32 SkillByQuestSort(int32 QuestSort) case QUEST_SORT_TAILORING: return SKILL_TAILORING; case QUEST_SORT_COOKING: return SKILL_COOKING; case QUEST_SORT_FIRST_AID: return SKILL_FIRST_AID; + case QUEST_SORT_JEWELCRAFTING: return SKILL_JEWELCRAFTING; + case QUEST_SORT_INSCRIPTION: return SKILL_INSCRIPTION; } return 0; } enum SkillCategory { - SKILL_CATEGORY_ATTRIBUTES = 5, - SKILL_CATEGORY_WEAPON = 6, - SKILL_CATEGORY_CLASS = 7, - SKILL_CATEGORY_ARMOR = 8, - SKILL_CATEGORY_SECONDARY = 9, // secondary professions + SKILL_CATEGORY_ATTRIBUTES = 5, + SKILL_CATEGORY_WEAPON = 6, + SKILL_CATEGORY_CLASS = 7, + SKILL_CATEGORY_ARMOR = 8, + SKILL_CATEGORY_SECONDARY = 9, // secondary professions SKILL_CATEGORY_LANGUAGES = 10, SKILL_CATEGORY_PROFESSION = 11, // primary professions - SKILL_CATEGORY_NOT_DISPLAYED = 12 + SKILL_CATEGORY_GENERIC = 12 }; enum TotemCategory { - TC_SKINNING_SKIFE = 1, + TC_SKINNING_SKIFE_OLD = 1, TC_EARTH_TOTEM = 2, TC_AIR_TOTEM = 3, TC_FIRE_TOTEM = 4, @@ -1895,15 +1948,28 @@ enum TotemCategory TC_GOLDEN_ROD = 8, TC_TRUESILVER_ROD = 9, TC_ARCANITE_ROD = 10, - TC_MINING_PICK = 11, + TC_MINING_PICK_OLD = 11, TC_PHILOSOPHERS_STONE = 12, - TC_BLACKSMITH_HAMMER = 13, + TC_BLACKSMITH_HAMMER_OLD = 13, TC_ARCLIGHT_SPANNER = 14, TC_GYROMATIC_MA = 15, TC_MASTER_TOTEM = 21, TC_FEL_IRON_ROD = 41, TC_ADAMANTITE_ROD = 62, - TC_ETERNIUM_ROD = 63 + TC_ETERNIUM_ROD = 63, + TC_HOLLOW_QUILL = 81, + TC_RUNED_AZURITE_ROD = 101, + TC_VIRTUOSO_INKING_SET = 121, + TC_DRUMS = 141, + TC_GNOMISH_ARMY_KNIFE = 161, + TC_BLACKSMITH_HAMMER = 162, + TC_MINING_PICK = 165, + TC_SKINNING_KNIFE = 166, + TC_HAMMER_PICK = 167, + TC_BLADED_PICKAXE = 168, + TC_FLINT_AND_TINDER = 169, + TC_RUNED_COBALT_ROD = 189, + TC_RUNED_TITANIUM_ROD = 190 }; enum UnitDynFlags @@ -1913,7 +1979,8 @@ enum UnitDynFlags UNIT_DYNFLAG_OTHER_TAGGER = 0x0004, UNIT_DYNFLAG_ROOTED = 0x0008, UNIT_DYNFLAG_SPECIALINFO = 0x0010, - UNIT_DYNFLAG_DEAD = 0x0020 + UNIT_DYNFLAG_DEAD = 0x0020, + UNIT_DYNFLAG_REFER_A_FRIEND = 0x0040 }; enum CorpseDynFlags @@ -1922,11 +1989,14 @@ enum CorpseDynFlags }; // Passive Spell codes explicit used in code -#define SPELL_ID_GENERIC_LEARN 483 -#define SPELL_ID_PASSIVE_BATTLE_STANCE 2457 -#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007 -#define SPELL_ID_WEAPON_SWITCH_COOLDOWN_1_5s 6119 -#define SPELL_ID_WEAPON_SWITCH_COOLDOWN_1_0s 6123 +#define SPELL_ID_GENERIC_LEARN 483 +#define SPELL_ID_GENERIC_LEARN_PET 55884 // used for learning mounts and companions +#define SPELL_ID_PASSIVE_BATTLE_STANCE 2457 +#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007 +#define SPELL_ID_WEAPON_SWITCH_COOLDOWN_1_5s 6119 +#define SPELL_ID_WEAPON_SWITCH_COOLDOWN_1_0s 6123 +#define SPELL_ID_AUTOSHOT 75 // used for checks in other spells interruption +#define SPELL_ID_SHADOWMELD 58984 // used for check ignore stealth stance state enum WeatherType { @@ -1990,9 +2060,12 @@ enum ChatMsg CHAT_MSG_BATTLEGROUND = 0x2C, CHAT_MSG_BATTLEGROUND_LEADER = 0x2D, CHAT_MSG_RESTRICTED = 0x2E, + CHAT_MSG_BN = 0x2F, + CHAT_MSG_ACHIEVEMENT = 0x30, + CHAT_MSG_GUILD_ACHIEVEMENT = 0x31 }; -#define MAX_CHAT_MSG_TYPE 0x2F +#define MAX_CHAT_MSG_TYPE 0x32 // Values from ItemPetFood (power of (value-1) used for compare with CreatureFamilyEntry.petDietMask enum PetDiet @@ -2092,7 +2165,9 @@ enum SummonType SUMMON_TYPE_CRITTER3 = 307, SUMMON_TYPE_UNKNOWN5 = 409, SUMMON_TYPE_POSESSED3 = 427, - SUMMON_TYPE_POSESSED2 = 428 + SUMMON_TYPE_POSESSED2 = 428, + SUMMON_TYPE_FORCE_OF_NATURE = 669, + SUMMON_TYPE_GUARDIAN2 = 1161 }; enum ResponseCodes @@ -2161,42 +2236,45 @@ enum ResponseCodes CHAR_CREATE_SERVER_QUEUE = 0x37, CHAR_CREATE_ONLY_EXISTING = 0x38, CHAR_CREATE_EXPANSION = 0x39, - - CHAR_DELETE_IN_PROGRESS = 0x3A, - CHAR_DELETE_SUCCESS = 0x3B, - CHAR_DELETE_FAILED = 0x3C, - CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x3D, - CHAR_DELETE_FAILED_GUILD_LEADER = 0x3E, - CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x3F, - - CHAR_LOGIN_IN_PROGRESS = 0x40, - CHAR_LOGIN_SUCCESS = 0x41, - CHAR_LOGIN_NO_WORLD = 0x42, - CHAR_LOGIN_DUPLICATE_CHARACTER = 0x43, - CHAR_LOGIN_NO_INSTANCES = 0x44, - CHAR_LOGIN_FAILED = 0x45, - CHAR_LOGIN_DISABLED = 0x46, - CHAR_LOGIN_NO_CHARACTER = 0x47, - CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x48, - CHAR_LOGIN_LOCKED_BY_BILLING = 0x49, - - CHAR_NAME_SUCCESS = 0x4A, - CHAR_NAME_FAILURE = 0x4B, - CHAR_NAME_NO_NAME = 0x4C, - CHAR_NAME_TOO_SHORT = 0x4D, - CHAR_NAME_TOO_LONG = 0x4E, - CHAR_NAME_INVALID_CHARACTER = 0x4F, - CHAR_NAME_MIXED_LANGUAGES = 0x50, - CHAR_NAME_PROFANE = 0x51, - CHAR_NAME_RESERVED = 0x52, - CHAR_NAME_INVALID_APOSTROPHE = 0x53, - CHAR_NAME_MULTIPLE_APOSTROPHES = 0x54, - CHAR_NAME_THREE_CONSECUTIVE = 0x55, - CHAR_NAME_INVALID_SPACE = 0x56, - CHAR_NAME_CONSECUTIVE_SPACES = 0x57, - CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x58, - CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x59, - CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x5A, + CHAR_CREATE_EXPANSION_CLASS = 0x3A, + CHAR_CREATE_LEVEL_REQUIREMENT = 0x3B, + CHAR_CREATE_UNIQUE_CLASS_LIMIT = 0x3C, + + CHAR_DELETE_IN_PROGRESS = 0x3D, + CHAR_DELETE_SUCCESS = 0x3E, + CHAR_DELETE_FAILED = 0x3F, + CHAR_DELETE_FAILED_LOCKED_FOR_TRANSFER = 0x40, + CHAR_DELETE_FAILED_GUILD_LEADER = 0x41, + CHAR_DELETE_FAILED_ARENA_CAPTAIN = 0x42, + + CHAR_LOGIN_IN_PROGRESS = 0x43, + CHAR_LOGIN_SUCCESS = 0x44, + CHAR_LOGIN_NO_WORLD = 0x45, + CHAR_LOGIN_DUPLICATE_CHARACTER = 0x46, + CHAR_LOGIN_NO_INSTANCES = 0x47, + CHAR_LOGIN_FAILED = 0x48, + CHAR_LOGIN_DISABLED = 0x49, + CHAR_LOGIN_NO_CHARACTER = 0x4A, + CHAR_LOGIN_LOCKED_FOR_TRANSFER = 0x4B, + CHAR_LOGIN_LOCKED_BY_BILLING = 0x4C, + + CHAR_NAME_SUCCESS = 0x4D, + CHAR_NAME_FAILURE = 0x4E, + CHAR_NAME_NO_NAME = 0x4F, + CHAR_NAME_TOO_SHORT = 0x50, + CHAR_NAME_TOO_LONG = 0x51, + CHAR_NAME_INVALID_CHARACTER = 0x52, + CHAR_NAME_MIXED_LANGUAGES = 0x53, + CHAR_NAME_PROFANE = 0x54, + CHAR_NAME_RESERVED = 0x55, + CHAR_NAME_INVALID_APOSTROPHE = 0x56, + CHAR_NAME_MULTIPLE_APOSTROPHES = 0x57, + CHAR_NAME_THREE_CONSECUTIVE = 0x58, + CHAR_NAME_INVALID_SPACE = 0x59, + CHAR_NAME_CONSECUTIVE_SPACES = 0x5A, + CHAR_NAME_RUSSIAN_CONSECUTIVE_SILENT_CHARACTERS = 0x5B, + CHAR_NAME_RUSSIAN_SILENT_CHARACTER_AT_BEGINNING_OR_END = 0x5C, + CHAR_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME = 0x5D }; /// Ban function modes @@ -2214,4 +2292,22 @@ enum BanReturn BAN_SYNTAX_ERROR, BAN_NOTFOUND }; + +// indexes of BattlemasterList.dbc +enum BattleGroundTypeId +{ + BATTLEGROUND_AV = 1, + BATTLEGROUND_WS = 2, + BATTLEGROUND_AB = 3, + BATTLEGROUND_NA = 4, + BATTLEGROUND_BE = 5, + BATTLEGROUND_AA = 6, + BATTLEGROUND_EY = 7, + BATTLEGROUND_RL = 8, + BATTLEGROUND_SA = 9, + BATTLEGROUND_DS = 10, + BATTLEGROUND_RV = 11 +}; +#define MAX_BATTLEGROUND_TYPE_ID 12 + #endif diff --git a/src/game/SkillDiscovery.cpp b/src/game/SkillDiscovery.cpp index 2a1c6ec9d82..f5e79bf220b 100644 --- a/src/game/SkillDiscovery.cpp +++ b/src/game/SkillDiscovery.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,14 +31,15 @@ struct SkillDiscoveryEntry { - uint32 spellId; - float chance; + uint32 spellId; // discavered spell + uint32 reqSkillValue; // skill level limitation + float chance; // chance SkillDiscoveryEntry() - : spellId(0), chance(0) {} + : spellId(0), reqSkillValue(0), chance(0) {} - SkillDiscoveryEntry(uint16 _spellId, float _chance) - : spellId(_spellId), chance(_chance) {} + SkillDiscoveryEntry(uint16 _spellId, uint32 req_skill_val, float _chance) + : spellId(_spellId), reqSkillValue(req_skill_val), chance(_chance) {} }; typedef std::list<SkillDiscoveryEntry> SkillDiscoveryList; @@ -53,8 +54,8 @@ void LoadSkillDiscoveryTable() uint32 count = 0; - // 0 1 2 - QueryResult *result = WorldDatabase.Query("SELECT spellId, reqSpell, chance FROM skill_discovery_template"); + // 0 1 2 3 + QueryResult *result = WorldDatabase.Query("SELECT spellId, reqSpell, reqSkillValue, chance FROM skill_discovery_template"); if (result) { @@ -69,11 +70,13 @@ void LoadSkillDiscoveryTable() uint32 spellId = fields[0].GetUInt32(); int32 reqSkillOrSpell = fields[1].GetInt32(); - float chance = fields[2].GetFloat(); + uint32 reqSkillValue = fields[2].GetInt32(); + float chance = fields[3].GetFloat(); if( chance <= 0 ) // chance { - ssNonDiscoverableEntries << "spellId = " << spellId << " reqSkillOrSpell = " << reqSkillOrSpell << " chance = " << chance << "\n"; + ssNonDiscoverableEntries << "spellId = " << spellId << " reqSkillOrSpell = " << reqSkillOrSpell + << " reqSkillValue = " << reqSkillValue << " chance = " << chance << "(chance problem)\n"; continue; } @@ -86,13 +89,16 @@ void LoadSkillDiscoveryTable() continue; } - if( spellEntry->Mechanic != MECHANIC_DISCOVERY ) + // mechanic discovery + if (spellEntry->Mechanic != MECHANIC_DISCOVERY && + // explicit discovery ability + !IsExplicitDiscoverySpell(spellEntry)) { - sLog.outErrorDb("Spell (ID: %u) not have have MECHANIC_DISCOVERY (28) value in Mechanic field in spell.dbc but listed in `skill_discovery_template` table",spellId); + sLog.outErrorDb("Spell (ID: %u) not have have MECHANIC_DISCOVERY (28) value in Mechanic field in spell.dbc and not 100% chance random discovery ability but listed in `skill_discovery_template` table",spellId); continue; } - SkillDiscoveryStore[reqSkillOrSpell].push_back( SkillDiscoveryEntry(spellId, chance) ); + SkillDiscoveryStore[reqSkillOrSpell].push_back( SkillDiscoveryEntry(spellId, reqSkillValue, chance) ); } else if( reqSkillOrSpell == 0 ) // skill case { @@ -107,7 +113,7 @@ void LoadSkillDiscoveryTable() for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) { - SkillDiscoveryStore[-int32(_spell_idx->second->skillId)].push_back( SkillDiscoveryEntry(spellId, chance) ); + SkillDiscoveryStore[-int32(_spell_idx->second->skillId)].push_back( SkillDiscoveryEntry(spellId, reqSkillValue, chance) ); } } else @@ -115,6 +121,7 @@ void LoadSkillDiscoveryTable() sLog.outErrorDb("Spell (ID: %u) have negative value in `reqSpell` field in `skill_discovery_template` table",spellId); continue; } + ++count; } while (result->NextRow()); @@ -132,8 +139,48 @@ void LoadSkillDiscoveryTable() } } +uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player) +{ + // explicit discovery spell chances (always success if case exist) + // in this case we have both skill and spell + SkillDiscoveryMap::iterator tab = SkillDiscoveryStore.find(spellId); + if(tab == SkillDiscoveryStore.end()) + return 0; + + SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(spellId); + SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(spellId); + uint32 skillvalue = lower != upper ? player->GetSkillValue(lower->second->skillId) : 0; + + float full_chance = 0; + for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter) + if(item_iter->reqSkillValue <= skillvalue) + if(!player->HasSpell(item_iter->spellId)) + full_chance += item_iter->chance; + + float rate = full_chance / 100.0f; + float roll = rand_chance() * rate; // roll now in range 0..full_chance + + for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter) + { + if(item_iter->reqSkillValue > skillvalue) + continue; + + if(player->HasSpell(item_iter->spellId)) + continue; + + if(item_iter->chance > roll) + return item_iter->spellId; + + roll -= item_iter->chance; + } + + return 0; +} + uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player) { + uint32 skillvalue = skillId ? player->GetSkillValue(skillId) : 0; + // check spell case SkillDiscoveryMap::iterator tab = SkillDiscoveryStore.find(spellId); @@ -142,6 +189,7 @@ uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player) for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter) { if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY)) + && item_iter->reqSkillValue <= skillvalue && !player->HasSpell(item_iter->spellId) ) return item_iter->spellId; } @@ -149,6 +197,9 @@ uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player) return 0; } + if(!skillId) + return 0; + // check skill line case tab = SkillDiscoveryStore.find(-(int32)skillId); if(tab != SkillDiscoveryStore.end()) @@ -156,6 +207,7 @@ uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player) for(SkillDiscoveryList::iterator item_iter = tab->second.begin(); item_iter != tab->second.end(); ++item_iter) { if( roll_chance_f(item_iter->chance * sWorld.getRate(RATE_SKILL_DISCOVERY)) + && item_iter->reqSkillValue <= skillvalue && !player->HasSpell(item_iter->spellId) ) return item_iter->spellId; } diff --git a/src/game/SkillDiscovery.h b/src/game/SkillDiscovery.h index bdd126e0cb3..9ee29c86810 100644 --- a/src/game/SkillDiscovery.h +++ b/src/game/SkillDiscovery.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,4 +27,5 @@ class Player; void LoadSkillDiscoveryTable(); uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player); +uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player); #endif diff --git a/src/game/SkillExtraItems.cpp b/src/game/SkillExtraItems.cpp index d4d46d8611d..67ec9719659 100644 --- a/src/game/SkillExtraItems.cpp +++ b/src/game/SkillExtraItems.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/SkillExtraItems.h b/src/game/SkillExtraItems.h index 904136cd9d3..5d71d8fd753 100644 --- a/src/game/SkillExtraItems.h +++ b/src/game/SkillExtraItems.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/SkillHandler.cpp b/src/game/SkillHandler.cpp index 56e48bf75c4..58c35fe463e 100644 --- a/src/game/SkillHandler.cpp +++ b/src/game/SkillHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -82,10 +82,6 @@ void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data ) } } - // Check if it requires spell - if( talentInfo->DependsOnSpell && !player->HasSpell(talentInfo->DependsOnSpell) ) - return; - // Find out how many points we have in this field uint32 spentPoints = 0; @@ -133,7 +129,7 @@ void WorldSession::HandleLearnTalentOpcode( WorldPacket & recv_data ) return; // learn! (other talent ranks will unlearned at learning) - GetPlayer( )->learnSpell(spellid); + GetPlayer( )->learnSpell(spellid,false); sLog.outDetail("TalentID: %u Rank: %u Spell: %u\n", talent_id, requested_rank, spellid); // update free talent points diff --git a/src/game/SocialMgr.cpp b/src/game/SocialMgr.cpp index baabe9b043f..a0851264451 100644 --- a/src/game/SocialMgr.cpp +++ b/src/game/SocialMgr.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -182,13 +182,6 @@ SocialMgr::~SocialMgr() } -void SocialMgr::RemovePlayerSocial(uint32 guid) -{ - SocialMap::iterator itr = m_socialMap.find(guid); - if(itr != m_socialMap.end()) - m_socialMap.erase(itr); -} - void SocialMgr::GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo) { if(!player) diff --git a/src/game/SocialMgr.h b/src/game/SocialMgr.h index 1cc14589e51..864cf8b2455 100644 --- a/src/game/SocialMgr.h +++ b/src/game/SocialMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -143,7 +143,8 @@ class SocialMgr SocialMgr(); ~SocialMgr(); // Misc - void RemovePlayerSocial(uint32 guid); + void RemovePlayerSocial(uint32 guid) { m_socialMap.erase(guid); } + void GetFriendInfo(Player *player, uint32 friendGUID, FriendInfo &friendInfo); // Packet management void MakeFriendStatusPacket(FriendsResult result, uint32 friend_guid, WorldPacket *data); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index d7d9446ab50..8d8f47f6379 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -43,7 +43,6 @@ #include "CellImpl.h" #include "Policies/SingletonImp.h" #include "SharedDefines.h" -#include "Tools.h" #include "LootMgr.h" #include "VMapFactory.h" #include "BattleGround.h" @@ -120,6 +119,14 @@ void SpellCastTargets::setDestination(Unit *target, bool send) m_targetMask |= TARGET_FLAG_DEST_LOCATION; } +void SpellCastTargets::setSource(float x, float y, float z) +{ + m_srcX = x; + m_srcY = y; + m_srcZ = z; + m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; +} + void SpellCastTargets::setGOTarget(GameObject *target) { m_GOTarget = target; @@ -178,16 +185,20 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) return true; // TARGET_FLAG_UNK2 is used for non-combat pets, maybe other? - if( m_targetMask & (TARGET_FLAG_UNIT|TARGET_FLAG_UNK2) ) - if(!readGUID(*data, m_unitTargetGUID)) + if( m_targetMask & ( TARGET_FLAG_UNIT | TARGET_FLAG_UNK2 )) + if(!data->readPackGUID(m_unitTargetGUID)) return false; - if( m_targetMask & ( TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK )) - if(!readGUID(*data, m_GOTargetGUID)) + if( m_targetMask & ( TARGET_FLAG_OBJECT )) + if(!data->readPackGUID(m_GOTargetGUID)) return false; if(( m_targetMask & ( TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM )) && caster->GetTypeId() == TYPEID_PLAYER) - if(!readGUID(*data, m_itemTargetGUID)) + if(!data->readPackGUID(m_itemTargetGUID)) + return false; + + if( m_targetMask & (TARGET_FLAG_CORPSE | TARGET_FLAG_PVP_CORPSE ) ) + if(!data->readPackGUID(m_CorpseTargetGUID)) return false; /*if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION ) @@ -202,7 +213,10 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) if( m_targetMask & (TARGET_FLAG_SOURCE_LOCATION | TARGET_FLAG_DEST_LOCATION) ) { - if(data->rpos()+4+4+4 > data->size()) + if(data->rpos()+1+4+4+4 > data->size()) + return false; + + if(!data->readPackGUID(m_unitTargetGUID)) return false; *data >> m_destX >> m_destY >> m_destZ; @@ -219,10 +233,6 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) *data >> m_strTarget; } - if( m_targetMask & (TARGET_FLAG_CORPSE | TARGET_FLAG_PVP_CORPSE ) ) - if(!readGUID(*data, m_CorpseTargetGUID)) - return false; - // find real units/GOs Update(caster); return true; @@ -242,7 +252,7 @@ void SpellCastTargets::write ( WorldPacket * data ) else *data << uint8(0); } - else if( m_targetMask & ( TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK ) ) + else if( m_targetMask & TARGET_FLAG_OBJECT ) { if(m_GOTarget) data->append(m_GOTarget->GetPackGUID()); @@ -267,7 +277,14 @@ void SpellCastTargets::write ( WorldPacket * data ) *data << m_srcX << m_srcY << m_srcZ; if( m_targetMask & TARGET_FLAG_DEST_LOCATION ) + { + if(m_unitTarget) + data->append(m_unitTarget->GetPackGUID()); + else + *data << uint8(0); + *data << m_destX << m_destY << m_destZ; + } if( m_targetMask & TARGET_FLAG_STRING ) *data << m_strTarget; @@ -305,7 +322,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi break; default: // Wands - if (m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_WAND) + if (m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG) m_attackType = RANGED_ATTACK; else m_attackType = BASE_ATTACK; @@ -355,14 +372,14 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi gameObjTarget = NULL; focusObject = NULL; m_cast_count = 0; + m_glyphIndex = 0; + m_preCastSpell = 0; m_triggeredByAuraSpell = NULL; - //Auto Shot & Shoot - if( m_spellInfo->AttributesEx2 == 0x000020 && !triggered ) - m_autoRepeat = true; - else - m_autoRepeat = false; + //Auto Shot & Shoot (wand) + m_autoRepeat = IsAutoRepeatRangedSpell(m_spellInfo); + m_runesState = 0; m_powerCost = 0; // setup to correct value in Spell::prepare, don't must be used before. m_casttime = 0; // setup to correct value in Spell::prepare, don't must be used before. m_timer = 0; // will set to castime in prepare @@ -372,7 +389,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi // determine reflection m_canReflect = false; - if(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && (m_spellInfo->AttributesEx2 & 0x4)==0) + if(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && !(m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_CANT_REFLECTED)) { for(int j=0;j<3;j++) { @@ -461,7 +478,7 @@ void Spell::FillTargetMap() WorldObject* result = NULL; Trinity::CannibalizeObjectCheck u_check(m_caster, max_range); - Trinity::WorldObjectSearcher<Trinity::CannibalizeObjectCheck > searcher(result, u_check); + Trinity::WorldObjectSearcher<Trinity::CannibalizeObjectCheck > searcher(m_caster, result, u_check); m_caster->VisitNearbyGridObject(max_range, searcher); if(!result) m_caster->VisitNearbyWorldObject(max_range, searcher); @@ -511,6 +528,8 @@ void Spell::FillTargetMap() case SPELL_EFFECT_CREATE_ITEM: case SPELL_EFFECT_TRIGGER_SPELL: case SPELL_EFFECT_SKILL_STEP: + case SPELL_EFFECT_PROFICIENCY: + case SPELL_EFFECT_SUMMON_OBJECT_WILD: case SPELL_EFFECT_SELF_RESURRECT: case SPELL_EFFECT_REPUTATION: case SPELL_EFFECT_LEARN_SPELL: @@ -543,7 +562,9 @@ void Spell::FillTargetMap() break; case SPELL_EFFECT_SUMMON_CHANGE_ITEM: case SPELL_EFFECT_ADD_FARSIGHT: + case SPELL_EFFECT_APPLY_GLYPH: case SPELL_EFFECT_STUCK: + case SPELL_EFFECT_FEED_PET: case SPELL_EFFECT_DESTROY_ALL_TOTEMS: tmpUnitMap.push_back(m_caster); break; @@ -553,9 +574,10 @@ void Spell::FillTargetMap() break; /*case SPELL_EFFECT_ENCHANT_ITEM: case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY: + case SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC: case SPELL_EFFECT_DISENCHANT: - case SPELL_EFFECT_FEED_PET: case SPELL_EFFECT_PROSPECTING: + case SPELL_EFFECT_MILLING: if(m_targets.getItemTarget()) AddItemTarget(m_targets.getItemTarget(), i); break;*/ @@ -596,7 +618,6 @@ void Spell::FillTargetMap() } } - if(IsChanneledSpell(m_spellInfo) && !tmpUnitMap.empty()) m_needAliveTargetMask |= (1<<i); @@ -633,34 +654,43 @@ void Spell::prepareDataForTriggerSystem() // Ñan spell trigger another or not ( m_canTrigger ) // Create base triggers flags for Attacker and Victim ( m_procAttacker and m_procVictim) //========================================================================================== - // Fill flag can spell trigger or not - if (!m_IsTriggeredSpell) + // TODO: possible exist spell attribute for this + m_canTrigger = false; + + if (m_CastItem) + m_canTrigger = false; // Do not trigger from item cast spell + else if (!m_IsTriggeredSpell) m_canTrigger = true; // Normal cast - can trigger else if (!m_triggeredByAuraSpell) m_canTrigger = true; // Triggered from SPELL_EFFECT_TRIGGER_SPELL - can trigger - else // Exceptions (some periodic triggers) + + if (!m_canTrigger) // Exceptions (some periodic triggers) { - m_canTrigger = false; // Triggered spells can`t trigger another switch (m_spellInfo->SpellFamilyName) { case SPELLFAMILY_MAGE: // Arcane Missles / Blizzard triggers need do it - if (m_spellInfo->SpellFamilyFlags & 0x0000000000200080LL) m_canTrigger = true; + if (m_spellInfo->SpellFamilyFlags[0] & 0x200080) m_canTrigger = true; break; case SPELLFAMILY_WARLOCK: // For Hellfire Effect / Rain of Fire / Seed of Corruption triggers need do it - if (m_spellInfo->SpellFamilyFlags & 0x0000800000000060LL) m_canTrigger = true; + if (m_spellInfo->SpellFamilyFlags[1] & 0x00008000 || m_spellInfo->SpellFamilyFlags[0] & 0x00000060) m_canTrigger = true; break; - case SPELLFAMILY_HUNTER: // Hunter Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect - if (m_spellInfo->SpellFamilyFlags & 0x0000200000000014LL) m_canTrigger = true; + case SPELLFAMILY_PRIEST: // For Penance heal/damage triggers need do it + if (m_spellInfo->SpellFamilyFlags[1] & 0x00018000) m_canTrigger = true; break; - case SPELLFAMILY_PALADIN: // For Holy Shock triggers need do it - if (m_spellInfo->SpellFamilyFlags & 0x0001000000200000LL) m_canTrigger = true; + case SPELLFAMILY_ROGUE: // For poisons need do it + if (m_spellInfo->SpellFamilyFlags[1] & 0x00000010 || m_spellInfo->SpellFamilyFlags[0] & 0x1001E000) m_canTrigger = true; + break; + case SPELLFAMILY_HUNTER: // Hunter Rapid Killing/Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect/Explosive Shot + if (m_spellInfo->SpellFamilyFlags[1] & 0x01002000 + || m_spellInfo->SpellFamilyFlags[0] & 0x00000214 || + m_spellInfo->SpellFamilyFlags[2] & 0x200) m_canTrigger = true; + break; + case SPELLFAMILY_PALADIN: // For Judgements (all) / Holy Shock triggers need do it + if (m_spellInfo->SpellFamilyFlags[1] & 0x00010009 || m_spellInfo->SpellFamilyFlags[0] & 0x00B80400) m_canTrigger = true; break; } } - // Do not trigger from item cast spell - if (m_CastItem) - m_canTrigger = false; // Get data for type of attack and fill base info for trigger switch (m_spellInfo->DmgClass) @@ -670,21 +700,30 @@ void Spell::prepareDataForTriggerSystem() m_procVictim = PROC_FLAG_TAKEN_MELEE_SPELL_HIT; break; case SPELL_DAMAGE_CLASS_RANGED: - m_procAttacker = PROC_FLAG_SUCCESSFUL_RANGED_SPELL_HIT; - m_procVictim = PROC_FLAG_TAKEN_RANGED_SPELL_HIT; + // Auto attack + if (m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG) + { + m_procAttacker = PROC_FLAG_SUCCESSFUL_RANGED_HIT; + m_procVictim = PROC_FLAG_TAKEN_RANGED_HIT; + } + else // Ranged spell attack + { + m_procAttacker = PROC_FLAG_SUCCESSFUL_RANGED_SPELL_HIT; + m_procVictim = PROC_FLAG_TAKEN_RANGED_SPELL_HIT; + } break; default: - if (IsPositiveSpell(m_spellInfo->Id)) // Check for positive spell + if (IsPositiveSpell(m_spellInfo->Id)) // Check for positive spell { m_procAttacker = PROC_FLAG_SUCCESSFUL_POSITIVE_SPELL; m_procVictim = PROC_FLAG_TAKEN_POSITIVE_SPELL; } - else if (m_spellInfo->Id == 5019) // Wands + else if (m_spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG) // Wands auto attack { - m_procAttacker = PROC_FLAG_SUCCESSFUL_RANGED_SPELL_HIT; - m_procVictim = PROC_FLAG_TAKEN_RANGED_SPELL_HIT; + m_procAttacker = PROC_FLAG_SUCCESSFUL_RANGED_HIT; + m_procVictim = PROC_FLAG_TAKEN_RANGED_HIT; } - else + else // Negative spell { m_procAttacker = PROC_FLAG_SUCCESSFUL_NEGATIVE_SPELL_HIT; m_procVictim = PROC_FLAG_TAKEN_NEGATIVE_SPELL_HIT; @@ -693,7 +732,7 @@ void Spell::prepareDataForTriggerSystem() } // Hunter traps spells (for Entrapment trigger) // Gives your Immolation Trap, Frost Trap, Explosive Trap, and Snake Trap .... - if (m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellInfo->SpellFamilyFlags & 0x0000200000000014LL) + if (m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && (m_spellInfo->SpellFamilyFlags[1] & 0x00002000 || m_spellInfo->SpellFamilyFlags[0] & 0x1C)) m_procAttacker |= PROC_FLAG_ON_TRAP_ACTIVATION; } @@ -702,8 +741,6 @@ void Spell::CleanupTargetList() m_UniqueTargetInfo.clear(); m_UniqueGOTargetInfo.clear(); m_UniqueItemInfo.clear(); - m_countOfHit = 0; - m_countOfMiss = 0; m_delayMoment = 0; } @@ -712,6 +749,9 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) if( m_spellInfo->Effect[effIndex]==0 ) return; + // Check for effect immune skip if immuned + bool immuned = pVictim->IsImmunedToSpellEffect(m_spellInfo, effIndex); + uint64 targetGUID = pVictim->GetGUID(); // Lookup target in already in list @@ -719,7 +759,8 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) { if (targetGUID == ihit->targetGUID) // Found in list { - ihit->effectMask |= 1<<effIndex; // Add only effect mask + if (!immuned) + ihit->effectMask |= 1<<effIndex; // Add only effect mask if not immuned return; } } @@ -729,7 +770,7 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) // Get spell hit result on target TargetInfo target; target.targetGUID = targetGUID; // Store target GUID - target.effectMask = 1<<effIndex; // Store index of effect + target.effectMask = immuned ? 0 : 1<<effIndex; // Store index of effect if not immuned target.processed = false; // Effects not apply on target target.damage = 0; @@ -743,11 +784,6 @@ void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex) else target.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE; - if (target.missCondition == SPELL_MISS_NONE) - ++m_countOfHit; - else - ++m_countOfMiss; - // Spell have speed - need calculate incoming time if (m_spellInfo->speed > 0.0f) { @@ -828,8 +864,6 @@ void Spell::AddGOTarget(GameObject* pVictim, uint32 effIndex) else target.timeDelay = 0LL; - ++m_countOfHit; - // Add target to list m_UniqueGOTargetInfo.push_back(target); } @@ -863,83 +897,6 @@ void Spell::AddItemTarget(Item* pitem, uint32 effIndex) target.effectMask = 1<<effIndex; m_UniqueItemInfo.push_back(target); } -/* -void Spell::doTriggers(SpellMissInfo missInfo, uint32 damage, SpellSchoolMask damageSchoolMask, uint32 block, uint32 absorb, bool crit) -{ - // Do triggers depends from hit result (triggers on hit do in effects) - // Set aura states depends from hit result - if (missInfo!=SPELL_MISS_NONE) - { - // Miss/dodge/parry/block only for melee based spells - // Resist only for magic based spells - switch (missInfo) - { - case SPELL_MISS_MISS: - if(m_caster->GetTypeId()== TYPEID_PLAYER) - ((Player*)m_caster)->UpdateWeaponSkill(BASE_ATTACK); - - m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_MISS, m_spellInfo, m_IsTriggeredSpell); - break; - case SPELL_MISS_RESIST: - m_caster->ProcDamageAndSpell(unitTarget, PROC_FLAG_TARGET_RESISTS, PROC_FLAG_RESIST_SPELL, 0, damageSchoolMask, m_spellInfo, m_IsTriggeredSpell); - break; - case SPELL_MISS_DODGE: - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - ((Player*)unitTarget)->UpdateDefense(); - - // Overpower - if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->getClass() == CLASS_WARRIOR) - { - ((Player*) m_caster)->AddComboPoints(unitTarget, 1); - m_caster->StartReactiveTimer( REACTIVE_OVERPOWER ); - } - - // Riposte - if (unitTarget->getClass() != CLASS_ROGUE) - { - unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true); - unitTarget->StartReactiveTimer( REACTIVE_DEFENSE ); - } - - m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_DODGE, m_spellInfo, m_IsTriggeredSpell); - break; - case SPELL_MISS_PARRY: - // Update victim defense ? - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - ((Player*)unitTarget)->UpdateDefense(); - // Mongoose bite - set only Counterattack here - if (unitTarget->getClass() == CLASS_HUNTER) - { - unitTarget->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true); - unitTarget->StartReactiveTimer( REACTIVE_HUNTER_PARRY ); - } - else - { - unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true); - unitTarget->StartReactiveTimer( REACTIVE_DEFENSE ); - } - m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_PARRY, m_spellInfo, m_IsTriggeredSpell); - break; - case SPELL_MISS_BLOCK: - unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true); - unitTarget->StartReactiveTimer( REACTIVE_DEFENSE ); - - m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_BLOCK, m_spellInfo, m_IsTriggeredSpell); - break; - // Trigger from this events not supported - case SPELL_MISS_EVADE: - case SPELL_MISS_IMMUNE: - case SPELL_MISS_IMMUNE2: - case SPELL_MISS_DEFLECT: - case SPELL_MISS_ABSORB: - // Trigger from reflects need do after get reflect result - case SPELL_MISS_REFLECT: - break; - default: - break; - } - } -}*/ void Spell::DoAllEffectOnTarget(TargetInfo *target) { @@ -949,15 +906,13 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) // Get mask of effects for target uint32 mask = target->effectMask; - if (mask == 0) // No effects - return; Unit* unit = m_caster->GetGUID()==target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster,target->targetGUID); if (!unit) return; // Get original caster (if exist) and calculate damage/healing from him data - Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster; + Unit *caster = m_originalCaster ? m_originalCaster : m_caster; // Skip if m_originalCaster not avaiable if (!caster) @@ -1005,7 +960,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) if (crit) { procEx |= PROC_EX_CRITICAL_HIT; - addhealth = caster->SpellCriticalBonus(m_spellInfo, addhealth, NULL); + addhealth = caster->SpellCriticalHealingBonus(m_spellInfo, addhealth, NULL); } else procEx |= PROC_EX_NORMAL_HIT; @@ -1044,44 +999,12 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) caster->DealSpellDamage(&damageInfo, true); - // Shadow Word: Death - deals damage equal to damage done to caster if victim is not killed - if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && m_spellInfo->SpellFamilyFlags&0x0000000200000000LL && - caster != unitTarget && unitTarget->isAlive()) - { - // Redirect damage to caster if victim Alive - damageInfo.target = caster; - damageInfo.absorb = 0; - damageInfo.resist = 0; - damageInfo.blocked = 0; - // Send log damage message to client - caster->SendSpellNonMeleeDamageLog(&damageInfo); - caster->DealSpellDamage(&damageInfo, true); - } // Judgement of Blood - else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && m_spellInfo->SpellFamilyFlags & 0x0000000800000000LL && m_spellInfo->SpellIconID==153) + if (m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && m_spellInfo->SpellFamilyFlags[1] & 0x00000008 && m_spellInfo->SpellIconID==153) { int32 damagePoint = damageInfo.damage * 33 / 100; m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true); } - // Bloodthirst - else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellInfo->SpellFamilyFlags & 0x40000000000LL) - { - uint32 BTAura = 0; - switch(m_spellInfo->Id) - { - case 23881: BTAura = 23885; break; - case 23892: BTAura = 23886; break; - case 23893: BTAura = 23887; break; - case 23894: BTAura = 23888; break; - case 25251: BTAura = 25252; break; - case 30335: BTAura = 30339; break; - default: - sLog.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo->Id); - break; - } - if (BTAura) - m_caster->CastSpell(m_caster,BTAura,true); - } } // Passive spell hits/misses or active spells only misses (only triggers) else @@ -1105,14 +1028,14 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target) if( !m_caster->IsFriendlyTo(unit) && !IsPositiveSpell(m_spellInfo->Id)) { - if( !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) ) + if( !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) ) { m_caster->CombatStart(unit); } else if(m_customAttr & SPELL_ATTR_CU_AURA_CC) { if(!unit->IsStandState()) - unit->SetStandState(PLAYER_STATE_NONE); + unit->SetStandState(UNIT_STAND_STATE_STAND); } } } @@ -1125,25 +1048,37 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) // Recheck immune (only for delayed spells) if( m_spellInfo->speed && !(m_spellInfo->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) - && (unit->IsImmunedToDamage(GetSpellSchoolMask(m_spellInfo),true) || - unit->IsImmunedToSpell(m_spellInfo,true) )) + && (unit->IsImmunedToDamage(GetSpellSchoolMask(m_spellInfo)) || + unit->IsImmunedToSpell(m_spellInfo))) { m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_IMMUNE); m_damage = 0; return; } + if (unit->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id); + ((Player*)unit)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id); + } + + if(m_caster->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, unit); + } + if( m_caster != unit ) { - if (unit->GetCharmerOrOwnerGUID() != m_caster->GetGUID()) + // Recheck UNIT_FLAG_NON_ATTACKABLE for delayed spells + if (m_spellInfo->speed > 0.0f && + unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) && + unit->GetCharmerOrOwnerGUID() != m_caster->GetGUID()) { - if (unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - { - m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); + m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); m_damage = 0; - return; - } + return; } + if( !m_caster->IsFriendlyTo(unit) ) { // for delayed spells ignore not visible explicit target @@ -1172,7 +1107,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) // assisting case, healing and resurrection if(unit->hasUnitState(UNIT_STAT_ATTACK_PLAYER)) m_caster->SetContestedPvP(); - if( unit->isInCombat() && !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) ) + if( unit->isInCombat() && !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO) ) { m_caster->SetInCombatState(unit->GetCombatTimer() > 0); unit->getHostilRefManager().threatAssist(m_caster, 0.0f); @@ -1190,6 +1125,10 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) unit->IncrDiminishing(m_diminishGroup); } + // Apply additional spell effects to target + if (m_preCastSpell) + m_caster->CastSpell(unit,m_preCastSpell, true, m_CastItem); + for(uint32 effectNumber=0;effectNumber<3;effectNumber++) { if (effectMask & (1<<effectNumber)) @@ -1349,6 +1288,16 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin if(!cur) return; + // Get spell max affected targets + /*uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets; + Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_MOD_MAX_AFFECTED_TARGETS); + for(Unit::AuraList::const_iterator m = mod.begin(); m != mod.end(); ++m) + { + if (!(*m)->isAffectedOnSpell(m_spellInfo)) + continue; + unMaxTargets+=(*m)->GetModifier()->m_amount; + }*/ + //FIXME: This very like horrible hack and wrong for most spells if(m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE) max_range += num * CHAIN_SPELL_JUMP_RADIUS; @@ -1460,7 +1409,7 @@ Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 en { Creature* target = NULL; Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster, entry, true, radius); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(target, u_check); + Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster, target, u_check); m_caster->VisitNearbyObject(radius, searcher); return target; } @@ -1474,13 +1423,13 @@ Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 en case SPELL_TARGETS_ENEMY: { Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius); - Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, u_check); + Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check); m_caster->VisitNearbyObject(radius, searcher); }break; case SPELL_TARGETS_ALLY: { Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius); - Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(target, u_check); + Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(m_caster, target, u_check); m_caster->VisitNearbyObject(radius, searcher); }break; } @@ -1499,6 +1448,13 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[i]; uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets; + Unit::AuraList const& Auras = m_caster->GetAurasByType(SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS); + for(Unit::AuraList::const_iterator j = Auras.begin();j != Auras.end(); ++j) + { + if((*j)->isAffectedOnSpell(m_spellInfo)) + unMaxTargets+=(*j)->GetModifier()->m_amount; + } + if(m_originalCaster) { if(Player* modOwner = m_originalCaster->GetSpellModOwner()) @@ -1537,10 +1493,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) m_caster->GetPartyMember(TagUnitMap, radius); break; case TARGET_UNIT_RAID: - if(Unit *target = m_targets.getUnitTarget()) - TagUnitMap.push_back(target); - else - m_caster->GetRaidMember(TagUnitMap, radius); + //if(Unit *target = m_targets.getUnitTarget()) + // TagUnitMap.push_back(target); + //else + m_caster->GetRaidMember(TagUnitMap, radius); + TagUnitMap.push_back(m_caster); break; } }break; @@ -1564,7 +1521,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) case TARGET_UNIT_TARGET_RAID: case TARGET_UNIT_TARGET_ANY: // SelectMagnetTarget()? case TARGET_UNIT_TARGET_PARTY: - case TARGET_UNIT_SINGLE_UNKNOWN: TagUnitMap.push_back(target); break; case TARGET_UNIT_PARTY_TARGET: @@ -1703,7 +1659,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) m_targets.setDestination(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, true, ((Player*)m_caster)->m_homebindMapId); break; - case TARGET_IN_FRONT_OF_CASTER: case TARGET_UNIT_CONE_ENEMY_UNKNOWN: if(m_customAttr & SPELL_ATTR_CU_CONE_BACK) @@ -1719,6 +1674,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) // nearby target case TARGET_UNIT_NEARBY_ALLY: + case TARGET_UNIT_NEARBY_ALLY_UNK: if(!m_targets.getUnitTarget()) m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ALLY)); if(m_targets.getUnitTarget()) @@ -1729,7 +1685,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) SearchChainTarget(TagUnitMap, radius, EffectChainTarget, SPELL_TARGETS_ALLY); } break; - case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA: + case TARGET_UNIT_NEARBY_ENEMY: if(!m_targets.getUnitTarget()) m_targets.setUnitTarget(SearchNearbyTarget(radius, SPELL_TARGETS_ENEMY)); if(m_targets.getUnitTarget()) @@ -1770,7 +1726,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) if(i_spellST->second.targetEntry) { Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range); - Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(p_GameObject,go_check); + Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(m_caster, p_GameObject,go_check); m_caster->VisitNearbyGridObject(range, checker); if(p_GameObject) @@ -1800,7 +1756,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) Creature *p_Creature = NULL; Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range); - Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(p_Creature, u_check); + Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster, p_Creature, u_check); m_caster->VisitNearbyObject(range, searcher); if(p_Creature ) @@ -2016,7 +1972,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) } } -void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura) +void Spell::prepare(SpellCastTargets const* targets, Aura* triggeredByAura) { if(m_CastItem) m_castItemGUID = m_CastItem->GetGUID(); @@ -2038,7 +1994,7 @@ void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura) m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1)); //Prevent casting at cast another spell (ServerSide check) - if(m_caster->IsNonMeleeSpellCasted(false, true) && m_cast_count) + if(m_caster->IsNonMeleeSpellCasted(false, true, true) && m_cast_count) { SendCastResult(SPELL_FAILED_SPELL_IN_PROGRESS); finish(false); @@ -2131,11 +2087,11 @@ void Spell::cancel(bool report) { Unit* unit = m_caster->GetGUID()==(*ihit).targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); if( unit && unit->isAlive() ) - unit->RemoveAurasDueToCasterSpell(m_spellInfo->Id, m_caster->GetGUID()); + unit->RemoveAurasByCasterSpell(m_spellInfo->Id, m_caster->GetGUID()); } } - m_caster->RemoveAurasDueToCasterSpell(m_spellInfo->Id, m_caster->GetGUID()); + m_caster->RemoveAurasByCasterSpell(m_spellInfo->Id, m_caster->GetGUID()); SendChannelUpdate(0); SendInterrupted(0); SendCastResult(report ? SPELL_FAILED_INTERRUPTED : SPELL_FAILED_DONT_REPORT); @@ -2212,16 +2168,43 @@ void Spell::cast(bool skipCheck) FillTargetMap(); - if(m_spellState == SPELL_STATE_FINISHED) // stop cast if spell marked as finish somewhere in Take*/FillTargetMap + if(m_spellInfo->SpellFamilyName) { - SetExecutedCurrently(false); - return; + if (m_spellInfo->excludeCasterAuraSpell) + m_preCastSpell = m_spellInfo->excludeCasterAuraSpell; + else if (m_spellInfo->excludeTargetAuraSpell) + m_preCastSpell = m_spellInfo->excludeTargetAuraSpell; } + switch (m_spellInfo->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages + m_preCastSpell = 11196; // Recently Bandaged + else if(m_spellInfo->SpellIconID == 1662 && m_spellInfo->AttributesEx & 0x20) + m_preCastSpell = 23230; // Blood Fury - Healing Reduction + break; + } + case SPELLFAMILY_PRIEST: + { + if (m_spellInfo->Id == 47585) // Dispersion (transform) + m_preCastSpell = 60069; // Dispersion (mana regen) + break; + } + } // traded items have trade slot instead of guid in m_itemTargetGUID // set to real guid to be sent later to the client m_targets.updateTradeSlotItem(); + if (m_caster->GetTypeId() == TYPEID_PLAYER) + { + if (m_CastItem) + ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry()); + + ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id); + } + if(!m_IsTriggeredSpell) { //TakePower(); @@ -2236,6 +2219,23 @@ void Spell::cast(bool skipCheck) if(m_customAttr & SPELL_ATTR_CU_DIRECT_DAMAGE) CalculateDamageDoneForAllTargets(); + //are there any spells need to be triggered after hit? + // handle SPELL_AURA_ADD_TARGET_TRIGGER auras + Unit::AuraList const& targetTriggers = m_caster->GetAurasByType(SPELL_AURA_ADD_TARGET_TRIGGER); + for(Unit::AuraList::const_iterator i = targetTriggers.begin(); i != targetTriggers.end(); ++i) + { + if (!(*i)->isAffectedOnSpell(m_spellInfo)) + continue; + SpellEntry const *auraSpellInfo = (*i)->GetSpellProto(); + uint32 auraSpellIdx = (*i)->GetEffIndex(); + if(SpellEntry const *spellInfo = sSpellStore.LookupEntry(auraSpellInfo->EffectTriggerSpell[auraSpellIdx])) + { + // Calculate chance at that moment (can be depend for example from combo points) + int32 chance = m_caster->CalculateSpellDamage(auraSpellInfo, auraSpellIdx, (*i)->GetBasePoints(), NULL); + m_ChanceTriggerSpells.push_back(std::make_pair(spellInfo, chance * (*i)->GetStackAmount())); + } + } + if(m_customAttr & SPELL_ATTR_CU_CHARGE) EffectCharge(0); @@ -2257,24 +2257,6 @@ void Spell::cast(bool skipCheck) handle_immediate(); } - //handle SPELL_AURA_ADD_TARGET_TRIGGER auras - //are there any spells need to be triggered after hit? - Unit::AuraList const& targetTriggers = m_caster->GetAurasByType(SPELL_AURA_ADD_TARGET_TRIGGER); - for(Unit::AuraList::const_iterator i = targetTriggers.begin(); i != targetTriggers.end(); ++i) - { - SpellEntry const *auraSpellInfo = (*i)->GetSpellProto(); - uint32 auraSpellIdx = (*i)->GetEffIndex(); - if (IsAffectedBy(auraSpellInfo, auraSpellIdx)) - { - if(SpellEntry const *spellInfo = sSpellStore.LookupEntry(auraSpellInfo->EffectTriggerSpell[auraSpellIdx])) - { - // Calculate chance at that moment (can be depend for example from combo points) - int32 chance = m_caster->CalculateSpellDamage(auraSpellInfo, auraSpellIdx, (*i)->GetBasePoints(), NULL); - m_ChanceTriggerSpells.push_back(std::make_pair(spellInfo, chance * (*i)->GetStackAmount())); - } - } - } - // combo points should not be taken before SPELL_AURA_ADD_TARGET_TRIGGER auras are handled if(!m_IsTriggeredSpell) { @@ -2299,9 +2281,18 @@ void Spell::handle_immediate() // start channeling if applicable if(IsChanneledSpell(m_spellInfo)) { - m_spellState = SPELL_STATE_CASTING; - m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags); - SendChannelStart(GetSpellDuration(m_spellInfo)); + int32 duration = GetSpellDuration(m_spellInfo); + if (duration) + { + //apply haste mods + m_caster->ModSpellCastTime(m_spellInfo, duration); + // Apply duration mod + if(Player* modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration); + m_spellState = SPELL_STATE_CASTING; + m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags); + SendChannelStart(duration); + } } // process immediate effects (items, ground, etc.) also initialize some variables @@ -2482,7 +2473,7 @@ void Spell::SendSpellCooldown() // shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK) // prevent 0 cooldowns set by another way - if (rec <= 0 && catrec <= 0 && (cat == 76 || cat == 351)) + if (rec <= 0 && catrec <= 0 && (cat == 76 || IsAutoRepeatRangedSpell(m_spellInfo) && m_spellInfo->Id != SPELL_ID_AUTOSHOT)) rec = _player->GetAttackTime(RANGED_ATTACK); // Now we have cooldown data (if found any), time to apply mods @@ -2520,7 +2511,7 @@ void Spell::SendSpellCooldown() if(*i_scset == m_spellInfo->Id) // skip main spell, already handled above continue; - _player->AddSpellCooldown(m_spellInfo->Id, m_CastItem ? m_CastItem->GetEntry() : 0, catrecTime); + _player->AddSpellCooldown(*i_scset, m_CastItem ? m_CastItem->GetEntry() : 0, catrecTime); } } } @@ -2698,9 +2689,9 @@ void Spell::SendCastResult(uint8 result) if(result != 0) { WorldPacket data(SMSG_CAST_FAILED, (4+1+1)); + data << uint8(m_cast_count); // single cast or multi 2.3 (0/1) data << uint32(m_spellInfo->Id); data << uint8(result); // problem - data << uint8(m_cast_count); // single cast or multi 2.3 (0/1) switch (result) { case SPELL_FAILED_REQUIRES_SPELL_FOCUS: @@ -2721,8 +2712,8 @@ void Spell::SendCastResult(uint8 result) case 45373: // Bloodberry Elixir data << uint32(4075); break; - default: // default case - data << uint32(m_spellInfo->AreaId); + default: // default case (don't must be) + data << uint32(0); break; } break; @@ -2741,18 +2732,11 @@ void Spell::SendCastResult(uint8 result) case SPELL_FAILED_EQUIPPED_ITEM_CLASS: data << uint32(m_spellInfo->EquippedItemClass); data << uint32(m_spellInfo->EquippedItemSubClassMask); - data << uint32(m_spellInfo->EquippedItemInventoryTypeMask); + //data << uint32(m_spellInfo->EquippedItemInventoryTypeMask); break; } ((Player*)m_caster)->GetSession()->SendPacket(&data); } - else - { - WorldPacket data(SMSG_CLEAR_EXTRA_AURA_INFO, (8+4)); - data.append(m_caster->GetPackGUID()); - data << uint32(m_spellInfo->Id); - ((Player*)m_caster)->GetSession()->SendPacket(&data); - } } void Spell::SendSpellStart() @@ -2766,6 +2750,9 @@ void Spell::SendSpellStart() if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; + if(m_spellInfo->runeCostID) + castFlags |= CAST_FLAG_UNKNOWN10; + Unit *target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster; WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); @@ -2775,14 +2762,32 @@ void Spell::SendSpellStart() data.append(m_caster->GetPackGUID()); data.append(m_caster->GetPackGUID()); - data << uint32(m_spellInfo->Id); - data << uint8(m_cast_count); // single cast or multi 2.3 (0/1) - data << uint16(castFlags); - data << uint32(m_timer); + data << uint8(m_cast_count); // pending spell cast? + data << uint32(m_spellInfo->Id); // spellId + data << uint32(castFlags); // cast flags + data << uint32(m_timer); // delay? m_targets.write(&data); - if( castFlags & CAST_FLAG_AMMO ) + if ( castFlags & CAST_FLAG_UNKNOWN6 ) // predicted power? + data << uint32(0); + + if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list + { + uint8 v1 = 0;//m_runesState; + uint8 v2 = 0;//((Player*)m_caster)->GetRunesState(); + data << uint8(v1); // runes state before + data << uint8(v2); // runes state after + for(uint8 i = 0; i < MAX_RUNES; ++i) + { + uint8 m = (1 << i); + if(m & v1) // usable before... + if(!(m & v2)) // ...but on cooldown now... + data << uint8(0); // some unknown byte (time?) + } + } + + if ( castFlags & CAST_FLAG_AMMO ) WriteAmmoToPacket(&data); m_caster->SendMessageToSet(&data, true); @@ -2802,24 +2807,68 @@ void Spell::SendSpellGo() if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual + if((m_caster->GetTypeId() == TYPEID_PLAYER) && (m_caster->getClass() == CLASS_DEATH_KNIGHT) && m_spellInfo->runeCostID) + { + castFlags |= CAST_FLAG_UNKNOWN10; // same as in SMSG_SPELL_START + castFlags |= CAST_FLAG_UNKNOWN6; // makes cooldowns visible + castFlags |= CAST_FLAG_UNKNOWN7; // rune cooldowns list + } + WorldPacket data(SMSG_SPELL_GO, 50); // guess size + if(m_CastItem) data.append(m_CastItem->GetPackGUID()); else data.append(m_caster->GetPackGUID()); data.append(m_caster->GetPackGUID()); - data << uint32(m_spellInfo->Id); - data << uint16(castFlags); + data << uint8(m_cast_count); // pending spell cast? + data << uint32(m_spellInfo->Id); // spellId + data << uint32(castFlags); // cast flags data << uint32(getMSTime()); // timestamp WriteSpellGoTargets(&data); m_targets.write(&data); - if( castFlags & CAST_FLAG_AMMO ) + if ( castFlags & CAST_FLAG_UNKNOWN6 ) // unknown wotlk, predicted power? + data << uint32(0); + + if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list + { + uint8 v1 = m_runesState; + uint8 v2 = ((Player*)m_caster)->GetRunesState(); + data << uint8(v1); // runes state before + data << uint8(v2); // runes state after + for(uint8 i = 0; i < MAX_RUNES; ++i) + { + uint8 m = (1 << i); + if(m & v1) // usable before... + if(!(m & v2)) // ...but on cooldown now... + data << uint8(0); // some unknown byte (time?) + } + } + + if ( castFlags & CAST_FLAG_UNKNOWN4 ) // unknown wotlk + { + data << float(0); + data << uint32(0); + } + + if ( castFlags & CAST_FLAG_AMMO ) WriteAmmoToPacket(&data); + if ( castFlags & CAST_FLAG_UNKNOWN5 ) // unknown wotlk + { + data << uint32(0); + data << uint32(0); + } + + if ( m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION ) + { + data << uint8(0); + } + m_caster->SendMessageToSet(&data, true); } @@ -2864,15 +2913,36 @@ void Spell::WriteAmmoToPacket( WorldPacket * data ) void Spell::WriteSpellGoTargets( WorldPacket * data ) { - *data << (uint8)m_countOfHit; + // This function also fill data for channeled spells: + // m_needAliveTargetMask req for stop channelig if one target die + uint32 hit = m_UniqueGOTargetInfo.size(); // Always hits on GO + uint32 miss = 0; + for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) + { + if ((*ihit).effectMask == 0) // No effect apply - all immuned add state + { + // possibly SPELL_MISS_IMMUNE2 for this?? + ihit->missCondition = SPELL_MISS_IMMUNE2; + miss++; + } + else if ((*ihit).missCondition == SPELL_MISS_NONE) + hit++; + else + miss++; + } + + *data << (uint8)hit; for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits + { *data << uint64(ihit->targetGUID); + m_needAliveTargetMask |=ihit->effectMask; + } for(std::list<GOTargetInfo>::iterator ighit= m_UniqueGOTargetInfo.begin();ighit != m_UniqueGOTargetInfo.end();++ighit) *data << uint64(ighit->targetGUID); // Always hits - *data << (uint8)m_countOfMiss; + *data << (uint8)miss; for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) { if( ihit->missCondition != SPELL_MISS_NONE ) // Add only miss @@ -2883,6 +2953,9 @@ void Spell::WriteSpellGoTargets( WorldPacket * data ) *data << uint8(ihit->reflectResult); } } + // Reset m_needAliveTargetMask for non channeled spell + if(!IsChanneledSpell(m_spellInfo)) + m_needAliveTargetMask = 0; } void Spell::SendLogExecute() @@ -2947,30 +3020,19 @@ void Spell::SendLogExecute() data << uint8(0); break; case SPELL_EFFECT_CREATE_ITEM: + case SPELL_EFFECT_CREATE_ITEM_2: data << uint32(m_spellInfo->EffectItemType[0]); break; case SPELL_EFFECT_SUMMON: - case SPELL_EFFECT_SUMMON_WILD: - case SPELL_EFFECT_SUMMON_GUARDIAN: case SPELL_EFFECT_TRANS_DOOR: case SPELL_EFFECT_SUMMON_PET: - case SPELL_EFFECT_SUMMON_POSSESSED: - case SPELL_EFFECT_SUMMON_TOTEM: case SPELL_EFFECT_SUMMON_OBJECT_WILD: case SPELL_EFFECT_CREATE_HOUSE: case SPELL_EFFECT_DUEL: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: - case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: - case SPELL_EFFECT_SUMMON_PHANTASM: - case SPELL_EFFECT_SUMMON_CRITTER: case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: - case SPELL_EFFECT_SUMMON_DEMON: - case SPELL_EFFECT_150: if(Unit *unit = m_targets.getUnitTarget()) data.append(unit->GetPackGUID()); else if(m_targets.getItemTargetGUID()) @@ -2989,6 +3051,13 @@ void Spell::SendLogExecute() else data << uint8(0); break; + case SPELL_EFFECT_RESURRECT: + case SPELL_EFFECT_RESURRECT_NEW: + if(Unit *unit = m_targets.getUnitTarget()) + data.append(unit->GetPackGUID()); + else + data << uint8(0); + break; default: return; } @@ -3002,13 +3071,16 @@ void Spell::SendInterrupted(uint8 result) { WorldPacket data(SMSG_SPELL_FAILURE, (8+4+1)); data.append(m_caster->GetPackGUID()); - data << m_spellInfo->Id; - data << result; + data << uint8(m_cast_count); + data << uint32(m_spellInfo->Id); + data << uint8(result); m_caster->SendMessageToSet(&data, true); data.Initialize(SMSG_SPELL_FAILED_OTHER, (8+4)); data.append(m_caster->GetPackGUID()); - data << m_spellInfo->Id; + data << uint8(m_cast_count); + data << uint32(m_spellInfo->Id); + data << uint8(result); m_caster->SendMessageToSet(&data, true); } @@ -3076,10 +3148,19 @@ void Spell::SendChannelStart(uint32 duration) void Spell::SendResurrectRequest(Player* target) { - WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+2+4)); - data << m_caster->GetGUID(); - data << uint32(1) << uint16(0) << uint32(1); + // Both players and NPCs can resurrect using spells - have a look at creature 28487 for example + // However, the packet structure differs slightly + + const char* sentName = m_caster->GetTypeId()==TYPEID_PLAYER ?"":m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex()); + + WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+strlen(sentName)+1+1+1)); + data << uint64(m_caster->GetGUID()); + data << uint32(strlen(sentName)+1); + + data << sentName; + data << uint8(0); + data << uint8(m_caster->GetTypeId()==TYPEID_PLAYER ?0:1); target->GetSession()->SendPacket(&data); } @@ -3132,7 +3213,7 @@ void Spell::TakeCastItem() if (charges) { (charges > 0) ? --charges : ++charges; // abs(charges) less at 1 after use - if (proto->Stackable < 2) + if (proto->Stackable == 1) m_CastItem->SetSpellCharges(i, charges); m_CastItem->SetState(ITEM_CHANGED, (Player*)m_caster); } @@ -3171,6 +3252,12 @@ void Spell::TakePower() { if(ihit->missCondition != SPELL_MISS_NONE && ihit->missCondition != SPELL_MISS_MISS/* && ihit->targetGUID!=m_caster->GetGUID()*/) hit = false; + if (ihit->missCondition != SPELL_MISS_NONE) + { + //lower spell cost on fail (by talent aura) + if(Player *modOwner = ((Player*)m_caster)->GetSpellModOwner()) + modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_SPELL_COST_REFUND_ON_FAIL, m_powerCost); + } break; } if(hit && NeedsComboPoints(m_spellInfo)) @@ -3192,6 +3279,12 @@ void Spell::TakePower() Powers powerType = Powers(m_spellInfo->powerType); + if(powerType == POWER_RUNE) + { + TakeRunePower(); + return; + } + if(hit) m_caster->ModifyPower(powerType, -m_powerCost); else @@ -3202,6 +3295,145 @@ void Spell::TakePower() m_caster->SetLastManaUse(getMSTime()); } +void Spell::TakeAmmo() +{ + if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER) + { + Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK ); + + // wands don't have ammo + if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND) + return; + + if( pItem->GetProto()->InventoryType == INVTYPE_THROWN ) + { + if(pItem->GetMaxStackCount()==1) + { + // decrease durability for non-stackable throw weapon + ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED); + } + else + { + // decrease items amount for stackable throw weapon + uint32 count = 1; + ((Player*)m_caster)->DestroyItemCount( pItem, count, true); + } + } + else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID)) + ((Player*)m_caster)->DestroyItemCount(ammo, 1, true); + } +} + +uint8 Spell::CheckRuneCost(uint32 runeCostID) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return 0; + + Player *plr = (Player*)m_caster; + + if(plr->getClass() != CLASS_DEATH_KNIGHT) + return 0; + + SpellRuneCostEntry const *src = sSpellRuneCostStore.LookupEntry(runeCostID); + + if(!src) + return 0; + + if(src->NoRuneCost()) + return 0; + + int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death + + for(uint32 i = 0; i < RUNE_DEATH; ++i) + { + runeCost[i] = src->RuneCost[i]; + } + + runeCost[RUNE_DEATH] = 0; // calculated later + + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + uint8 rune = plr->GetCurrentRune(i); + if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0)) + { + runeCost[rune]--; + } + } + + for(uint32 i = 0; i < RUNE_DEATH; ++i) + { + if(runeCost[i] > 0) + { + runeCost[RUNE_DEATH] += runeCost[i]; + } + } + + if(runeCost[RUNE_DEATH] > 0) + return SPELL_FAILED_NO_POWER; // not sure if result code is correct + + return 0; +} + +void Spell::TakeRunePower() +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *plr = (Player*)m_caster; + + if(plr->getClass() != CLASS_DEATH_KNIGHT) + return; + + SpellRuneCostEntry const *src = sSpellRuneCostStore.LookupEntry(m_spellInfo->runeCostID); + + if(!src || (src->NoRuneCost() && src->NoRunicPowerGain())) + return; + + m_runesState = plr->GetRunesState(); // store previous state + + int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death + + for(uint32 i = 0; i < RUNE_DEATH; ++i) + { + runeCost[i] = src->RuneCost[i]; + } + + runeCost[RUNE_DEATH] = 0; // calculated later + + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + uint8 rune = plr->GetCurrentRune(i); + if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0)) + { + plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec + runeCost[rune]--; + } + } + + runeCost[RUNE_DEATH] = runeCost[RUNE_BLOOD] + runeCost[RUNE_UNHOLY] + runeCost[RUNE_FROST]; + + if(runeCost[RUNE_DEATH] > 0) + { + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + uint8 rune = plr->GetCurrentRune(i); + if((plr->GetRuneCooldown(i) == 0) && (rune == RUNE_DEATH)) + { + plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec + runeCost[rune]--; + plr->ConvertRune(i, plr->GetBaseRune(i)); + if(runeCost[RUNE_DEATH] == 0) + break; + } + } + } + + // you can gain some runic power when use runes + float rp = src->runePowerGain;; + rp *= sWorld.getRate(RATE_POWER_RUNICPOWER_INCOME); + plr->ModifyPower(POWER_RUNIC_POWER, (int32)rp); +} + void Spell::TakeReagents() { if(m_IsTriggeredSpell) // reagents used in triggered spell removed by original spell or don't must be removed. @@ -3210,11 +3442,9 @@ void Spell::TakeReagents() if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - if (m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP && - m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION)) - return; - Player* p_caster = (Player*)m_caster; + if (p_caster->CanNoReagentCast(m_spellInfo)) + return; for(uint32 x=0;x<8;x++) { @@ -3277,14 +3507,9 @@ void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTar gameObjTarget = pGOTarget; uint8 eff = m_spellInfo->Effect[i]; - uint32 mechanic = m_spellInfo->EffectMechanic[i]; sLog.outDebug( "Spell: Effect : %u", eff); - //Simply return. Do not display "immune" in red text on client - if(unitTarget && unitTarget->IsImmunedToSpellEffect(eff, mechanic)) - return; - //we do not need DamageMultiplier here. damage = CalculateDamage(i, NULL); @@ -3322,6 +3547,9 @@ uint8 Spell::CanCast(bool strict) // check cooldowns to prevent cheating if(m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->HasSpellCooldown(m_spellInfo->Id)) { + //can cast triggered (by aura only?) spells while have this flag + if (!m_IsTriggeredSpell && ((Player*)m_caster)->HasFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY)) + return SPELL_FAILED_SPELL_IN_PROGRESS; if(m_triggeredByAuraSpell) return SPELL_FAILED_DONT_REPORT; else @@ -3338,19 +3566,55 @@ uint8 Spell::CanCast(bool strict) // for now, ignore triggered spells if( strict && !m_IsTriggeredSpell) { - // Cannot be used in this stance/form - if(uint8 shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, m_caster->m_form)) - return shapeError; + bool checkForm = true; + // Ignore form req aura + Unit::AuraList const& ignore = m_caster->GetAurasByType(SPELL_AURA_MOD_IGNORE_SHAPESHIFT); + for(Unit::AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) + { + if (!(*i)->isAffectedOnSpell(m_spellInfo)) + continue; + checkForm = false; + break; + } + if (checkForm) + { + // Cannot be used in this stance/form + if(uint8 shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, m_caster->m_form)) + return shapeError; + + if ((m_spellInfo->Attributes & SPELL_ATTR_ONLY_STEALTHED) && !(m_caster->HasStealthAura())) + return SPELL_FAILED_ONLY_STEALTHED; + } + } + + bool reqAuraState=true; + Unit::AuraList const& stateAuras = m_caster->GetAurasByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE); + for(Unit::AuraList::const_iterator j = stateAuras.begin();j != stateAuras.end(); ++j) + { + if((*j)->isAffectedOnSpell(m_spellInfo)) + { + reqAuraState=false; + break; + } + } + + if (reqAuraState) + { + // caster state requirements + if(m_spellInfo->CasterAuraState && !m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraState))) + return SPELL_FAILED_CASTER_AURASTATE; + if(m_spellInfo->CasterAuraStateNot && m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraStateNot))) + return SPELL_FAILED_CASTER_AURASTATE; - if ((m_spellInfo->Attributes & SPELL_ATTR_ONLY_STEALTHED) && !(m_caster->HasStealthAura())) - return SPELL_FAILED_ONLY_STEALTHED; + if(m_spellInfo->casterAuraSpell && !m_caster->HasAura(m_spellInfo->casterAuraSpell)) + return SPELL_FAILED_CASTER_AURASTATE; + if(m_spellInfo->excludeCasterAuraSpell && m_caster->HasAura(m_spellInfo->excludeCasterAuraSpell)) + return SPELL_FAILED_CASTER_AURASTATE; + + if(m_caster->isInCombat() && IsNonCombatSpell(m_spellInfo)) + return SPELL_FAILED_AFFECTING_COMBAT; } - // caster state requirements - if(m_spellInfo->CasterAuraState && !m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraState))) - return SPELL_FAILED_CASTER_AURASTATE; - if(m_spellInfo->CasterAuraStateNot && m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraStateNot))) - return SPELL_FAILED_CASTER_AURASTATE; // cancel autorepeat spells if cast start when moving // (not wand currently autorepeat cast delayed to moving stop anyway in spell update code) @@ -3366,14 +3630,23 @@ uint8 Spell::CanCast(bool strict) if(target) { - // target state requirements (not allowed state), apply to self also - if(m_spellInfo->TargetAuraStateNot && target->HasAuraState(AuraState(m_spellInfo->TargetAuraStateNot))) - return SPELL_FAILED_TARGET_AURASTATE; + if (reqAuraState) + { + // target state requirements (not allowed state), apply to self also + if(m_spellInfo->TargetAuraStateNot && target->HasAuraState(AuraState(m_spellInfo->TargetAuraStateNot))) + return SPELL_FAILED_TARGET_AURASTATE; + + if(m_spellInfo->targetAuraSpell && !target->HasAura(m_spellInfo->targetAuraSpell)) + return SPELL_FAILED_TARGET_AURASTATE; + + if(m_spellInfo->excludeTargetAuraSpell && target->HasAura(m_spellInfo->excludeTargetAuraSpell)) + return SPELL_FAILED_TARGET_AURASTATE; + } if(target != m_caster) { // target state requirements (apply to non-self only), to allow cast affects to self like Dirty Deeds - if(m_spellInfo->TargetAuraState && !target->HasAuraState(AuraState(m_spellInfo->TargetAuraState))) + if(reqAuraState && m_spellInfo->TargetAuraState && !target->HasAuraState(AuraState(m_spellInfo->TargetAuraState))) return SPELL_FAILED_TARGET_AURASTATE; // Not allow casting on flying player @@ -3395,6 +3668,20 @@ uint8 Spell::CanCast(bool strict) } } } + else if (m_caster->GetTypeId()==TYPEID_PLAYER) // Target - is player caster + { + // Additional check for some spells + // If 0 spell effect empty - client not send target data (need use selection) + // TODO: check it on next client version + if (m_targets.m_targetMask == TARGET_FLAG_SELF && + m_spellInfo->EffectImplicitTargetA[1] == TARGET_CHAIN_DAMAGE) + { + if (target = m_caster->GetUnit(*m_caster, ((Player *)m_caster)->GetSelection())) + m_targets.setUnitTarget(target); + else + return SPELL_FAILED_BAD_TARGETS; + } + } // check pet presents for(int j=0;j<3;j++) @@ -3446,13 +3733,16 @@ uint8 Spell::CanCast(bool strict) if(IsPositiveSpell(m_spellInfo->Id)) { - if(target->IsImmunedToSpell(m_spellInfo,false)) + if(target->IsImmunedToSpell(m_spellInfo)) return SPELL_FAILED_TARGET_AURASTATE; } //Must be behind the target. if( m_spellInfo->AttributesEx2 == 0x100000 && (m_spellInfo->AttributesEx & 0x200) == 0x200 && target->HasInArc(M_PI, m_caster) - && (m_spellInfo->SpellFamilyName != SPELLFAMILY_DRUID || m_spellInfo->SpellFamilyFlags != 0x0000000000020000LL)) + //Exclusion for Pounce: Facing Limitation was removed in 2.0.1, but it still uses the same, old Ex-Flags + && (!(m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags.IsEqual(0x20000,0,0))) + //Multilate - same reason + && (!(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellInfo->SpellFamilyFlags[1] & 200000))) { SendInterrupted(2); return SPELL_FAILED_NOT_BEHIND; @@ -3486,8 +3776,9 @@ uint8 Spell::CanCast(bool strict) return SPELL_FAILED_NOT_IN_ARENA; // zone check - if(!IsSpellAllowedInLocation(m_spellInfo,m_caster->GetMapId(),m_caster->GetZoneId(),m_caster->GetAreaId())) - return SPELL_FAILED_REQUIRES_AREA; + if (uint8 res= GetSpellAllowedInLocationError(m_spellInfo,m_caster->GetMapId(),m_caster->GetZoneId(),m_caster->GetAreaId(), + m_caster->GetTypeId()==TYPEID_PLAYER ? ((Player*)m_caster)->GetBattleGroundId() : 0)) + return res; // not let players cast spells at mount (and let do it to creatures) if( m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell && @@ -3540,7 +3831,7 @@ uint8 Spell::CanCast(bool strict) cell.data.Part.reserved = ALL_DISTRICT; MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range); - MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck> checker(p_GameObject,go_check); + MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck> checker(m_caster, p_GameObject,go_check); TypeContainerVisitor<MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker); CellLock<GridReadGuard> cell_lock(cell, p); @@ -3578,7 +3869,7 @@ uint8 Spell::CanCast(bool strict) cell.SetNoCreate(); // Really don't know what is that??? MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range); - MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(p_Creature, u_check); + MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(m_caster, p_Creature, u_check); TypeContainerVisitor<MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher); @@ -3686,7 +3977,7 @@ uint8 Spell::CanCast(bool strict) case SPELL_EFFECT_SCHOOL_DAMAGE: { // Hammer of Wrath - if(m_spellInfo->SpellVisual == 7250) + if(m_spellInfo->SpellVisual[0] == 7250) { if (!m_targets.getUnitTarget()) return SPELL_FAILED_BAD_IMPLICIT_TARGETS; @@ -3711,15 +4002,9 @@ uint8 Spell::CanCast(bool strict) if(!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; - if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id)) - return SPELL_FAILED_TOO_MANY_SKILLS; - if(m_spellInfo->spellLevel > pet->getLevel()) return SPELL_FAILED_LOWLEVEL; - if(!pet->HasTPForSpell(learn_spellproto->Id)) - return SPELL_FAILED_TRAINING_POINTS; - break; } case SPELL_EFFECT_LEARN_PET_SPELL: @@ -3734,20 +4019,18 @@ uint8 Spell::CanCast(bool strict) if(!learn_spellproto) return SPELL_FAILED_NOT_KNOWN; - if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id)) - return SPELL_FAILED_TOO_MANY_SKILLS; - if(m_spellInfo->spellLevel > pet->getLevel()) return SPELL_FAILED_LOWLEVEL; - if(!pet->HasTPForSpell(learn_spellproto->Id)) - return SPELL_FAILED_TRAINING_POINTS; - break; } case SPELL_EFFECT_FEED_PET: { - if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_targets.getItemTarget() ) + if (m_caster->GetTypeId() != TYPEID_PLAYER) + return SPELL_FAILED_BAD_TARGETS; + + Item* foodItem = m_targets.getItemTarget(); + if(!foodItem) return SPELL_FAILED_BAD_TARGETS; Pet* pet = m_caster->GetPet(); @@ -3755,10 +4038,10 @@ uint8 Spell::CanCast(bool strict) if(!pet) return SPELL_FAILED_NO_PET; - if(!pet->HaveInDiet(m_targets.getItemTarget()->GetProto())) + if(!pet->HaveInDiet(foodItem->GetProto())) return SPELL_FAILED_WRONG_PET_FOOD; - if(!pet->GetCurrentFoodBenefitLevel(m_targets.getItemTarget()->GetProto()->ItemLevel)) + if(!pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel)) return SPELL_FAILED_FOOD_LOWLEVEL; if(m_caster->isInCombat() || pet->isInCombat()) @@ -3845,27 +4128,27 @@ uint8 Spell::CanCast(bool strict) { // check for lock - key pair (checked by client also, just prevent cheating bool ok_key = false; - for(int it = 0; it < 5; ++it) + for(int it = 0; it < 8; ++it) { - switch(lockInfo->keytype[it]) + switch(lockInfo->Type[it]) { case LOCK_KEY_NONE: break; case LOCK_KEY_ITEM: { - if(lockInfo->key[it]) + if(lockInfo->Index[it]) { - if(m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it]) + if(m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[it]) ok_key =true; break; } } case LOCK_KEY_SKILL: { - if(uint32(m_spellInfo->EffectMiscValue[i])!=lockInfo->key[it]) + if(uint32(m_spellInfo->EffectMiscValue[i])!=lockInfo->Index[it]) break; - switch(lockInfo->key[it]) + switch(lockInfo->Index[it]) { case LOCKTYPE_HERBALISM: if(((Player*)m_caster)->HasSkill(SKILL_HERBALISM)) @@ -3923,9 +4206,9 @@ uint8 Spell::CanCast(bool strict) { // check for lock - key pair bool ok = false; - for(int it = 0; it < 5; ++it) + for(int it = 0; it < 8; ++it) { - if(lockInfo->keytype[it]==LOCK_KEY_ITEM && lockInfo->key[it] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it]) + if(lockInfo->Type[it]==LOCK_KEY_ITEM && lockInfo->Index[it] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[it]) { // if so, we're good to go ok = true; @@ -3936,9 +4219,9 @@ uint8 Spell::CanCast(bool strict) break; if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_PICKLOCK) - ReqValue = lockInfo->requiredlockskill; + ReqValue = lockInfo->Skill[1]; else - ReqValue = lockInfo->requiredminingskill; + ReqValue = lockInfo->Skill[0]; } // skill doesn't meet the required value @@ -3962,9 +4245,7 @@ uint8 Spell::CanCast(bool strict) break; } - // This is generic summon effect now and don't make this check for summon types similar - // SPELL_EFFECT_SUMMON_CRITTER, SPELL_EFFECT_SUMMON_WILD or SPELL_EFFECT_SUMMON_GUARDIAN. - // These won't show up in m_caster->GetPetGUID() + // This is generic summon effect case SPELL_EFFECT_SUMMON: { switch(m_spellInfo->EffectMiscValueB[i]) @@ -3985,11 +4266,8 @@ uint8 Spell::CanCast(bool strict) } break; } - // Don't make this check for SPELL_EFFECT_SUMMON_CRITTER, SPELL_EFFECT_SUMMON_WILD or SPELL_EFFECT_SUMMON_GUARDIAN. - // These won't show up in m_caster->GetPetGUID() - case SPELL_EFFECT_SUMMON_POSSESSED: + // Not used for summon? case SPELL_EFFECT_SUMMON_PHANTASM: - case SPELL_EFFECT_SUMMON_DEMON: { if(m_caster->GetPetGUID()) return SPELL_FAILED_ALREADY_HAVE_SUMMON; @@ -4134,17 +4412,14 @@ uint8 Spell::CanCast(bool strict) return SPELL_FAILED_NO_MOUNTS_ALLOWED; // Ignore map check if spell have AreaId. AreaId already checked and this prevent special mount spells - if (m_caster->GetTypeId()==TYPEID_PLAYER && !sMapStore.LookupEntry(m_caster->GetMapId())->IsMountAllowed() && !m_IsTriggeredSpell && !m_spellInfo->AreaId) - return SPELL_FAILED_NO_MOUNTS_ALLOWED; - - if (m_caster->GetAreaId()==35) + if (m_caster->GetTypeId()==TYPEID_PLAYER && !sMapStore.LookupEntry(m_caster->GetMapId())->IsMountAllowed() && !m_IsTriggeredSpell && !m_spellInfo->AreaGroupId) return SPELL_FAILED_NO_MOUNTS_ALLOWED; ShapeshiftForm form = m_caster->m_form; if( form == FORM_CAT || form == FORM_TREE || form == FORM_TRAVEL || form == FORM_AQUA || form == FORM_BEAR || form == FORM_DIREBEAR || form == FORM_CREATUREBEAR || form == FORM_GHOSTWOLF || form == FORM_FLIGHT || - form == FORM_FLIGHT_EPIC || form == FORM_MOONKIN ) + form == FORM_FLIGHT_EPIC || form == FORM_MOONKIN || form == FORM_METAMORPHOSIS ) return SPELL_FAILED_NOT_SHAPESHIFT; break; @@ -4163,11 +4438,10 @@ uint8 Spell::CanCast(bool strict) case SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED: case SPELL_AURA_FLY: { - // not allow cast fly spells at old maps by players (all spells is self target) + // not allow cast fly spells at old maps by players (all spells is self target) if(m_caster->GetTypeId()==TYPEID_PLAYER) { - if( !((Player*)m_caster)->isGameMaster() && - GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) != 530) + if( !((Player*)m_caster)->IsAllowUseFlyMountsHere() ) return SPELL_FAILED_NOT_HERE; } break; @@ -4282,15 +4556,16 @@ uint8 Spell::CheckCasterAuras() const //Check whether the cast should be prevented by any state you might have. uint8 prevented_reason = 0; // Have to check if there is a stun aura. Otherwise will have problems with ghost aura apply while logging out - if(!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED) && m_caster->HasAuraType(SPELL_AURA_MOD_STUN)) + uint32 unitflag = m_caster->GetUInt32Value(UNIT_FIELD_FLAGS); // Get unit state + if(unitflag & UNIT_FLAG_STUNNED && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED)) prevented_reason = SPELL_FAILED_STUNNED; - else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED) && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED)) + else if(unitflag & UNIT_FLAG_CONFUSED && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED)) prevented_reason = SPELL_FAILED_CONFUSED; - else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING) && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED)) + else if(unitflag & UNIT_FLAG_FLEEING && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED)) prevented_reason = SPELL_FAILED_FLEEING; - else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE) + else if(unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE) prevented_reason = SPELL_FAILED_SILENCED; - else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY) + else if(unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY) prevented_reason = SPELL_FAILED_PACIFIED; // Attr must make flag drop spell totally immune from all effects @@ -4481,9 +4756,12 @@ int32 Spell::CalculatePowerCost() case POWER_FOCUS: case POWER_ENERGY: case POWER_HAPPINESS: - // case POWER_RUNES: powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetMaxPower(Powers(m_spellInfo->powerType)) / 100; break; + case POWER_RUNE: + case POWER_RUNIC_POWER: + sLog.outDebug("Spell::CalculateManaCost: Not implemented yet!"); + break; default: sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", m_spellInfo->powerType, m_spellInfo->Id); return 0; @@ -4528,6 +4806,11 @@ uint8 Spell::CheckPower() sLog.outError("Spell::CheckMana: Unknown power type '%d'", m_spellInfo->powerType); return SPELL_FAILED_UNKNOWN; } + + uint8 failReason = CheckRuneCost(m_spellInfo->runeCostID); + if(failReason) + return failReason; + // Check power amount Powers powerType = Powers(m_spellInfo->powerType); if(m_caster->GetPower(powerType) < m_powerCost) @@ -4647,8 +4930,8 @@ uint8 Spell::CheckItems() cell.data.Part.reserved = ALL_DISTRICT; GameObject* ok = NULL; - Trinity::GameObjectFocusCheck go_check(m_caster,m_spellInfo->RequiresSpellFocus); - Trinity::GameObjectSearcher<Trinity::GameObjectFocusCheck> checker(ok,go_check); + MaNGOS::GameObjectFocusCheck go_check(m_caster,m_spellInfo->RequiresSpellFocus); + MaNGOS::GameObjectSearcher<MaNGOS::GameObjectFocusCheck> checker(m_caster,ok,go_check); TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectFocusCheck>, GridTypeMapContainer > object_checker(checker); CellLock<GridReadGuard> cell_lock(cell, p); @@ -4660,8 +4943,7 @@ uint8 Spell::CheckItems() focusObject = ok; // game object found in range } - if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP && - m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION))) + if (!p_caster->CanNoReagentCast(m_spellInfo)) { for(uint32 i=0;i<8;i++) { @@ -4746,6 +5028,7 @@ uint8 Spell::CheckItems() break; } case SPELL_EFFECT_ENCHANT_ITEM: + case SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC: { Item* targetItem = m_targets.getItemTarget(); if(!targetItem) @@ -4829,13 +5112,36 @@ uint8 Spell::CheckItems() return SPELL_FAILED_LOW_CASTLEVEL; //make sure the player has the required ores in inventory if(m_targets.getItemTarget()->GetCount() < 5) - return SPELL_FAILED_PROSPECT_NEED_MORE; + return SPELL_FAILED_NEED_MORE_ITEMS; if(!LootTemplates_Prospecting.HaveLootFor(m_targets.getItemTargetEntry())) return SPELL_FAILED_CANT_BE_PROSPECTED; break; } + case SPELL_EFFECT_MILLING: + { + if(!m_targets.getItemTarget()) + return SPELL_FAILED_CANT_BE_MILLED; + //ensure item is a millable herb + if(!(m_targets.getItemTarget()->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS) || m_targets.getItemTarget()->GetProto()->Class != ITEM_CLASS_TRADE_GOODS) + return SPELL_FAILED_CANT_BE_MILLED; + //prevent milling in trade slot + if( m_targets.getItemTarget()->GetOwnerGUID() != m_caster->GetGUID() ) + return SPELL_FAILED_CANT_BE_MILLED; + //Check for enough skill in inscription + uint32 item_millingskilllevel = m_targets.getItemTarget()->GetProto()->RequiredSkillRank; + if(item_millingskilllevel >p_caster->GetSkillValue(SKILL_INSCRIPTION)) + return SPELL_FAILED_LOW_CASTLEVEL; + //make sure the player has the required herbs in inventory + if(m_targets.getItemTarget()->GetCount() < 5) + return SPELL_FAILED_NEED_MORE_ITEMS; + + if(!LootTemplates_Milling.HaveLootFor(m_targets.getItemTargetEntry())) + return SPELL_FAILED_CANT_BE_MILLED; + + break; + } case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: { @@ -4915,18 +5221,22 @@ void Spell::Delayed() // only called in DealDamage() //if (m_spellState == SPELL_STATE_DELAYED) // return; // spell is active and can't be time-backed + if(isDelayableNoMore()) // Spells may only be delayed twice + return; + // spells not loosing casting time ( slam, dynamites, bombs.. ) //if(!(m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE)) // return; - //check resist chance - int32 resistChance = 100; //must be initialized to 100 for percent modifiers - ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this); - resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100; - if (roll_chance_i(resistChance)) + //check pushback reduce + int32 delaytime = 500; // spellcasting delay is normally 500ms + int32 delayReduce = 100; // must be initialized to 100 for percent modifiers + ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME, delayReduce, this); + delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100; + if(delayReduce >= 100) return; - int32 delaytime = GetNextDelayAtDamageMsTime(); + delaytime = delaytime * (100 - delayReduce) / 100; if(int32(m_timer) + delaytime > m_casttime) { @@ -4950,14 +5260,18 @@ void Spell::DelayedChannel() if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER || getState() != SPELL_STATE_CASTING) return; - //check resist chance - int32 resistChance = 100; //must be initialized to 100 for percent modifiers - ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this); - resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100; - if (roll_chance_i(resistChance)) + if(isDelayableNoMore()) // Spells may only be delayed twice + return; + + //check pushback reduce + int32 delaytime = GetSpellDuration(m_spellInfo) * 25 / 100; // channeling delay is normally 25% of its time per hit + int32 delayReduce = 100; // must be initialized to 100 for percent modifiers + ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,delayReduce, this); + delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100; + if(delayReduce >= 100) return; - int32 delaytime = GetNextDelayAtDamageMsTime(); + delaytime = delaytime * (100 - delayReduce) / 100; if(int32(m_timer) < delaytime) { @@ -5011,9 +5325,9 @@ void Spell::UpdatePointers() m_targets.Update(m_caster); } -bool Spell::IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId) +bool Spell::IsAffectedByAura(Aura *aura) { - return spellmgr.IsAffectedBySpell(m_spellInfo,spellInfo->Id,effectId,spellInfo->EffectItemType[effectId]); + return spellmgr.IsAffectedByMod(m_spellInfo, aura->getAuraSpellMod()); } bool Spell::CheckTargetCreatureType(Unit* target) const @@ -5021,7 +5335,7 @@ bool Spell::CheckTargetCreatureType(Unit* target) const uint32 spellCreatureTargetMask = m_spellInfo->TargetCreatureType; // Curse of Doom : not find another way to fix spell target check :/ - if(m_spellInfo->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags == 0x0200000000LL) + if(m_spellInfo->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags.IsEqual(0,0x02,0)) { // not allow cast at player if(target->GetTypeId()==TYPEID_PLAYER) @@ -5064,6 +5378,12 @@ bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase ) return false; } + // Check Aura spell req (need for AoE spells) + if(m_spellInfo->targetAuraSpell && !target->HasAura(m_spellInfo->targetAuraSpell)) + return false; + if (m_spellInfo->excludeTargetAuraSpell && target->HasAura(m_spellInfo->excludeTargetAuraSpell)) + return false; + // Check targets for not_selectable unit flag and remove // A player can cast spells on his pet (or other controlled unit) though in any state if (target != m_caster && target->GetCharmerOrOwnerGUID() != m_caster->GetGUID()) @@ -5124,7 +5444,13 @@ bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase ) // all ok by some way or another, skip normal check break; default: // normal case - if(target!=m_caster && !target->IsWithinLOSInMap(m_caster)) + // Get GO cast coordinates if original caster -> GO + WorldObject *caster = NULL; + if (m_originalCasterGUID) + caster = ObjectAccessor::GetGameObject(*m_caster, m_originalCasterGUID); + if (!caster) + caster = m_caster; + if(target!=m_caster && !target->IsWithinLOSInMap(caster)) return false; break; } @@ -5143,9 +5469,8 @@ Unit* Spell::SelectMagnetTarget() { if(Unit* magnet = (*itr)->GetCaster()) { - if((*itr)->m_procCharges>0) + if((*itr)->DropAuraCharge()) { - (*itr)->SetAuraProcCharges((*itr)->m_procCharges-1); target = magnet; m_targets.setUnitTarget(target); AddUnitTarget(target, 0); @@ -5169,7 +5494,7 @@ Unit* Spell::SelectMagnetTarget() bool Spell::IsNeedSendToClient() const { - return m_spellInfo->SpellVisual!=0 || IsChanneledSpell(m_spellInfo) || + return m_spellInfo->SpellVisual[0] || m_spellInfo->SpellVisual[1] || IsChanneledSpell(m_spellInfo) || m_spellInfo->speed > 0.0f || !m_triggeredByAuraSpell && !m_IsTriggeredSpell; } @@ -5350,6 +5675,14 @@ void Spell::CalculateDamageDoneForAllTargets() } } + bool usesAmmo=true; + Unit::AuraList const& Auras = m_caster->GetAurasByType(SPELL_AURA_ABILITY_CONSUME_NO_AMMO); + for(Unit::AuraList::const_iterator j = Auras.begin();j != Auras.end(); ++j) + { + if((*j)->isAffectedOnSpell(m_spellInfo)) + usesAmmo=false; + } + for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { TargetInfo &target = *ihit; @@ -5362,6 +5695,28 @@ void Spell::CalculateDamageDoneForAllTargets() if (!unit) continue; + if (usesAmmo) + { + bool ammoTaken=false; + for (uint8 i=0;i<3;i++) + { + if (!(mask & 1<<i)) + continue; + switch (m_spellInfo->Effect[i]) + { + case SPELL_EFFECT_SCHOOL_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE: + case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: + case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: + case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: + ammoTaken=true; + TakeAmmo(); + } + if (ammoTaken) + break; + } + } + if (target.missCondition==SPELL_MISS_NONE) // In case spell hit target, do all effect on that target target.damage += CalculateDamageDone(unit, mask, multiplier); else if (target.missCondition == SPELL_MISS_REFLECT) // In case spell reflect from target, do all effect on caster (if hit) diff --git a/src/game/Spell.h b/src/game/Spell.h index 42725aa11c7..9f29d3bf8d7 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,26 +47,51 @@ enum SpellCastTargetFlags TARGET_FLAG_RESURRECTABLE = 0x8000*/ TARGET_FLAG_SELF = 0x00000000, + TARGET_FLAG_UNUSED1 = 0x00000001, // not used in any spells as of 3.0.3 (can be set dynamically) TARGET_FLAG_UNIT = 0x00000002, // pguid + TARGET_FLAG_UNUSED2 = 0x00000004, // not used in any spells as of 3.0.3 (can be set dynamically) + TARGET_FLAG_UNUSED3 = 0x00000008, // not used in any spells as of 3.0.3 (can be set dynamically) TARGET_FLAG_ITEM = 0x00000010, // pguid TARGET_FLAG_SOURCE_LOCATION = 0x00000020, // 3 float TARGET_FLAG_DEST_LOCATION = 0x00000040, // 3 float - TARGET_FLAG_OBJECT_UNK = 0x00000080, // ? + TARGET_FLAG_OBJECT_UNK = 0x00000080, // used in 7 spells only + TARGET_FLAG_UNIT_UNK = 0x00000100, // looks like self target (480 spells) TARGET_FLAG_PVP_CORPSE = 0x00000200, // pguid - TARGET_FLAG_OBJECT = 0x00000800, // pguid - TARGET_FLAG_TRADE_ITEM = 0x00001000, // pguid - TARGET_FLAG_STRING = 0x00002000, // string - TARGET_FLAG_UNK1 = 0x00004000, // ? - TARGET_FLAG_CORPSE = 0x00008000, // pguid - TARGET_FLAG_UNK2 = 0x00010000 // pguid + TARGET_FLAG_UNIT_CORPSE = 0x00000400, // 10 spells (gathering professions) + TARGET_FLAG_OBJECT = 0x00000800, // pguid, 2 spells + TARGET_FLAG_TRADE_ITEM = 0x00001000, // pguid, 0 spells + TARGET_FLAG_STRING = 0x00002000, // string, 0 spells + TARGET_FLAG_UNK1 = 0x00004000, // 199 spells, opening object/lock + TARGET_FLAG_CORPSE = 0x00008000, // pguid, resurrection spells + TARGET_FLAG_UNK2 = 0x00010000, // pguid, not used in any spells as of 3.0.3 (can be set dynamically) + TARGET_FLAG_GLYPH = 0x00020000 // used in glyph spells }; enum SpellCastFlags { + CAST_FLAG_NONE = 0x00000000, + CAST_FLAG_UNKNOWN0 = 0x00000001, // may be pending spell cast CAST_FLAG_UNKNOWN1 = 0x00000002, + CAST_FLAG_UNKNOWN11 = 0x00000004, + CAST_FLAG_UNKNOWN12 = 0x00000008, CAST_FLAG_UNKNOWN2 = 0x00000010, - CAST_FLAG_AMMO = 0x00000020, - CAST_FLAG_UNKNOWN3 = 0x00000100 + CAST_FLAG_AMMO = 0x00000020, // Projectiles visual + CAST_FLAG_UNKNOWN8 = 0x00000040, + CAST_FLAG_UNKNOWN9 = 0x00000080, + CAST_FLAG_UNKNOWN3 = 0x00000100, + CAST_FLAG_UNKNOWN13 = 0x00000200, + CAST_FLAG_UNKNOWN14 = 0x00000400, + CAST_FLAG_UNKNOWN6 = 0x00000800, // wotlk, trigger rune cooldown + CAST_FLAG_UNKNOWN15 = 0x00001000, + CAST_FLAG_UNKNOWN16 = 0x00002000, + CAST_FLAG_UNKNOWN17 = 0x00004000, + CAST_FLAG_UNKNOWN18 = 0x00008000, + CAST_FLAG_UNKNOWN19 = 0x00010000, + CAST_FLAG_UNKNOWN4 = 0x00020000, // wotlk + CAST_FLAG_UNKNOWN10 = 0x00040000, + CAST_FLAG_UNKNOWN5 = 0x00080000, // wotlk + CAST_FLAG_UNKNOWN20 = 0x00100000, + CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk, rune cooldown list }; enum SpellRangeFlag @@ -136,6 +161,7 @@ class SpellCastTargets void setUnitTarget(Unit *target); void setDestination(float x, float y, float z, bool send = true, int32 mapId = -1); void setDestination(Unit *target, bool send = true); + void setSource(float x, float y, float z); uint64 getGOTargetGUID() const { return m_GOTargetGUID; } GameObject *getGOTarget() const { return m_GOTarget; } @@ -234,6 +260,7 @@ class Spell void EffectHealthLeech(uint32 i); void EffectQuestComplete(uint32 i); void EffectCreateItem(uint32 i); + void EffectCreateItem2(uint32 i); void EffectPersistentAA(uint32 i); void EffectEnergize(uint32 i); void EffectOpenLock(uint32 i); @@ -276,6 +303,7 @@ class Spell void EffectStuck(uint32 i); void EffectSummonPlayer(uint32 i); void EffectActivateObject(uint32 i); + void EffectApplyGlyph(uint32 i); void EffectSummonTotem(uint32 i); void EffectEnchantHeldItem(uint32 i); void EffectSummonObject(uint32 i); @@ -293,6 +321,8 @@ class Spell void EffectSkinning(uint32 i); void EffectCharge(uint32 i); void EffectProspecting(uint32 i); + void EffectMilling(uint32 i); + void EffectRenamePet(uint32 i); void EffectSendTaxi(uint32 i); void EffectSummonCritter(uint32 i); void EffectKnockBack(uint32 i); @@ -319,16 +349,22 @@ class Spell void EffectKillCredit(uint32 i); void EffectQuestFail(uint32 i); void EffectRedirectThreat(uint32 i); + void EffectActivateRune(uint32 i); + void EffectTitanGrip(uint32 i); + void EffectEnchantItemPrismatic(uint32 i); Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL, bool skipCheck = false ); ~Spell(); - void prepare(SpellCastTargets * targets, Aura* triggeredByAura = NULL); + void prepare(SpellCastTargets const* targets, Aura* triggeredByAura = NULL); void cancel(bool report = true); void update(uint32 difftime); void cast(bool skipCheck = false); void finish(bool ok = true); void TakePower(); + void TakeAmmo(); + uint8 CheckRuneCost(uint32 runeCostID); + void TakeRunePower(); void TakeReagents(); void TakeCastItem(); void TriggerSpell(); @@ -354,11 +390,10 @@ class Spell bool HaveTargetsForEffect(uint8 effect) const; void Delayed(); void DelayedChannel(); - inline uint32 getState() const { return m_spellState; } + uint32 getState() const { return m_spellState; } void setState(uint32 state) { m_spellState = state; } void DoCreateItem(uint32 i, uint32 itemtype); - void WriteSpellGoTargets( WorldPacket * data ); void WriteAmmoToPacket( WorldPacket * data ); void FillTargetMap(); @@ -388,6 +423,8 @@ class Spell Item* m_CastItem; uint64 m_castItemGUID; uint8 m_cast_count; + uint32 m_glyphIndex; + uint32 m_preCastSpell; SpellCastTargets m_targets; int32 GetCastTime() const { return m_casttime; } @@ -424,7 +461,7 @@ class Spell void UpdatePointers(); // must be used at call Spell code after time delay (non triggered spell cast/update spell call/etc) - bool IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId); + bool IsAffectedByAura(Aura *aura); bool CheckTargetCreatureType(Unit* target) const; @@ -451,9 +488,17 @@ class Spell int32 m_casttime; // Calculated spell cast time initialized only in Spell::prepare bool m_canReflect; // can reflect this spell? bool m_autoRepeat; + uint8 m_runesState; uint8 m_delayAtDamageCount; - int32 GetNextDelayAtDamageMsTime() { return m_delayAtDamageCount < 5 ? 1000 - (m_delayAtDamageCount++)* 200 : 200; } + bool isDelayableNoMore() + { + if(m_delayAtDamageCount >= 2) + return true; + + m_delayAtDamageCount++; + return false; + } // Delayed spells system uint64 m_delayStart; // time of spell delay start, filled by event handler, zero = just started @@ -497,8 +542,6 @@ class Spell // Spell target subsystem //***************************************** // Targets store structures and data - uint32 m_countOfHit; - uint32 m_countOfMiss; struct TargetInfo { uint64 targetGUID; diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index cf628515925..b5a33052341 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,14 +20,19 @@ #ifndef TRINITY_SPELLAURADEFINES_H #define TRINITY_SPELLAURADEFINES_H -#define MAX_AURAS 56 -#define MAX_POSITIVE_AURAS 40 +#define MAX_AURAS 64 // client support up to 255, but it will cause problems with group auras updating enum AURA_FLAGS { - AFLAG_NEGATIVE = 0x09, - AFLAG_POSITIVE = 0x1F, - AFLAG_MASK = 0xFF + AFLAG_NONE = 0x00, + AFLAG_EFF_INDEX_0 = 0x01, + AFLAG_EFF_INDEX_1 = 0x02, + AFLAG_EFF_INDEX_2 = 0x04, + AFLAG_NOT_CASTER = 0x08, + AFLAG_POSITIVE = 0x10, + AFLAG_DURATION = 0x20, + AFLAG_UNK2 = 0x40, + AFLAG_NEGATIVE = 0x80 }; //m_schoolAbsorb @@ -85,11 +90,11 @@ enum AuraType SPELL_AURA_PROC_TRIGGER_DAMAGE = 43, SPELL_AURA_TRACK_CREATURES = 44, SPELL_AURA_TRACK_RESOURCES = 45, - SPELL_AURA_MOD_PARRY_SKILL = 46, + SPELL_AURA_46 = 46, // Ignore all Gear test spells SPELL_AURA_MOD_PARRY_PERCENT = 47, - SPELL_AURA_MOD_DODGE_SKILL = 48, + SPELL_AURA_48 = 48, // One periodic spell SPELL_AURA_MOD_DODGE_PERCENT = 49, - SPELL_AURA_MOD_BLOCK_SKILL = 50, + SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT = 50, SPELL_AURA_MOD_BLOCK_PERCENT = 51, SPELL_AURA_MOD_CRIT_PERCENT = 52, SPELL_AURA_PERIODIC_LEECH = 53, @@ -104,7 +109,7 @@ enum AuraType SPELL_AURA_PERIODIC_HEALTH_FUNNEL = 62, SPELL_AURA_PERIODIC_MANA_FUNNEL = 63, SPELL_AURA_PERIODIC_MANA_LEECH = 64, - SPELL_AURA_MOD_CASTING_SPEED = 65, + SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK = 65, SPELL_AURA_FEIGN_DEATH = 66, SPELL_AURA_MOD_DISARM = 67, SPELL_AURA_MOD_STALKED = 68, @@ -184,11 +189,11 @@ enum AuraType SPELL_AURA_MOD_BASE_RESISTANCE_PCT = 142, SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE = 143, SPELL_AURA_SAFE_FALL = 144, - SPELL_AURA_CHARISMA = 145, - SPELL_AURA_PERSUADED = 146, - SPELL_AURA_ADD_CREATURE_IMMUNITY = 147, + SPELL_AURA_MOD_PET_TALENT_POINTS = 145, + SPELL_AURA_ALLOW_TAME_PET_TYPE = 146, + SPELL_AURA_MECHANIC_IMMUNITY_MASK = 147, SPELL_AURA_RETAIN_COMBO_POINTS = 148, - SPELL_AURA_RESIST_PUSHBACK = 149, // Resist Pushback + SPELL_AURA_REDUCE_PUSHBACK = 149, // Reduce Pushback SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT = 150, SPELL_AURA_TRACK_STEALTHED = 151, // Track Stealthed SPELL_AURA_MOD_DETECTED_RANGE = 152, // Mod Detected Range @@ -233,8 +238,8 @@ enum AuraType SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED = 191, SPELL_AURA_HASTE_MELEE = 192, SPELL_AURA_MELEE_SLOW = 193, - SPELL_AURA_MOD_DEPRICATED_1 = 194, // not used now, old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT - SPELL_AURA_MOD_DEPRICATED_2 = 195, // not used now, old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT + SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL = 194, + SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL = 195, SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197, SPELL_AURA_MOD_ALL_WEAPON_SKILLS = 198, @@ -266,16 +271,16 @@ enum AuraType SPELL_AURA_224 = 224, SPELL_AURA_PRAYER_OF_MENDING = 225, SPELL_AURA_PERIODIC_DUMMY = 226, - SPELL_AURA_227 = 227, + SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE = 227, SPELL_AURA_DETECT_STEALTH = 228, SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE = 229, SPELL_AURA_230 = 230, - SPELL_AURA_231 = 231, + SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE = 231, SPELL_AURA_MECHANIC_DURATION_MOD = 232, SPELL_AURA_233 = 233, SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK = 234, SPELL_AURA_MOD_DISPEL_RESIST = 235, - SPELL_AURA_236 = 236, + SPELL_AURA_CONTROL_VEHICLE = 236, SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER = 237, SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER = 238, SPELL_AURA_MOD_SCALE_2 = 239, @@ -284,29 +289,52 @@ enum AuraType SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING = 242, SPELL_AURA_243 = 243, SPELL_AURA_COMPREHEND_LANGUAGE = 244, - SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS = 245, - SPELL_AURA_246 = 246, + SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL = 245, + SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK = 246, SPELL_AURA_247 = 247, SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248, - SPELL_AURA_249 = 249, + SPELL_AURA_CONVERT_RUNE = 249, SPELL_AURA_MOD_INCREASE_HEALTH_2 = 250, SPELL_AURA_MOD_ENEMY_DODGE = 251, SPELL_AURA_252 = 252, - SPELL_AURA_253 = 253, - SPELL_AURA_254 = 254, - SPELL_AURA_255 = 255, - SPELL_AURA_256 = 256, - SPELL_AURA_257 = 257, + SPELL_AURA_MOD_BLOCK_CRIT_CHANCE = 253, + SPELL_AURA_MOD_DISARM_OFFHAND = 254, + SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT = 255, + SPELL_AURA_NO_REAGENT_USE = 256, + SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS = 257, SPELL_AURA_258 = 258, - SPELL_AURA_259 = 259, - SPELL_AURA_260 = 260, - SPELL_AURA_261 = 261, - TOTAL_AURAS=262 + SPELL_AURA_MOD_HOT_PCT = 259, + SPELL_AURA_SCREEN_EFFECT = 260, + SPELL_AURA_PHASE = 261, + SPELL_AURA_ABILITY_IGNORE_AURASTATE = 262, + SPELL_AURA_ALLOW_ONLY_ABILITY = 263, + SPELL_AURA_264 = 264, + SPELL_AURA_265 = 265, + SPELL_AURA_266 = 266, + SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL = 267, + SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268, + SPELL_AURA_MOD_IGNORE_TARGET_RESIST = 269, + SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST = 270, // Possibly need swap vs 195 aura used only in 1 spell Chaos Bolt Passive + SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271, + SPELL_AURA_272 = 272, + SPELL_AURA_273 = 273, + SPELL_AURA_ABILITY_CONSUME_NO_AMMO = 274, + SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275, + SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done + SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS = 277, + SPELL_AURA_MOD_DISARM_RANGED = 278, + SPELL_AURA_279 = 279, + SPELL_AURA_MOD_WEAPONTYPE_IGNORE_TARGET_RESISTANCE = 280, + SPELL_AURA_MOD_HONOR_GAIN_PCT = 281, + SPELL_AURA_MOD_BASE_HEALTH_PCT = 282, + SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells + TOTAL_AURAS = 284 }; enum AreaAuraType { AREA_AURA_PARTY, + AREA_AURA_RAID, AREA_AURA_FRIEND, AREA_AURA_ENEMY, AREA_AURA_PET, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index c77e84b85f5..0896ba99a59 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -100,11 +100,11 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor &Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES &Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES - &Aura::HandleUnused, // 46 SPELL_AURA_MOD_PARRY_SKILL obsolete? + &Aura::HandleUnused, // 46 SPELL_AURA_46 &Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT - &Aura::HandleUnused, // 48 SPELL_AURA_MOD_DODGE_SKILL obsolete? + &Aura::HandleUnused, // 48 SPELL_AURA_48 &Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT - &Aura::HandleUnused, // 50 SPELL_AURA_MOD_BLOCK_SKILL obsolete? + &Aura::HandleNoImmediateEffect, // 50 SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT implemented in Unit::SpellCriticalHealingBonus &Aura::HandleAuraModBlockPercent, // 51 SPELL_AURA_MOD_BLOCK_PERCENT &Aura::HandleAuraModCritPercent, // 52 SPELL_AURA_MOD_CRIT_PERCENT &Aura::HandlePeriodicLeech, // 53 SPELL_AURA_PERIODIC_LEECH @@ -116,10 +116,10 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, // 59 SPELL_AURA_MOD_DAMAGE_DONE_CREATURE implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus &Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE &Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE - &Aura::HandleNULL, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL + &Aura::HandlePeriodicHealthFunnel, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL &Aura::HandleUnused, // 63 SPELL_AURA_PERIODIC_MANA_FUNNEL obsolete? &Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH - &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED + &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK &Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH &Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM &Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED @@ -163,7 +163,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraHover, //106 SPELL_AURA_HOVER &Aura::HandleAddModifier, //107 SPELL_AURA_ADD_FLAT_MODIFIER &Aura::HandleAddModifier, //108 SPELL_AURA_ADD_PCT_MODIFIER - &Aura::HandleNoImmediateEffect, //109 SPELL_AURA_ADD_TARGET_TRIGGER + &Aura::HandleAddTargetTrigger, //109 SPELL_AURA_ADD_TARGET_TRIGGER &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT &Aura::HandleNULL, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS @@ -199,11 +199,11 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE &Aura::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes - &Aura::HandleUnused, //145 SPELL_AURA_CHARISMA obsolete? - &Aura::HandleUnused, //146 SPELL_AURA_PERSUADED obsolete? - &Aura::HandleNULL, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY + &Aura::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS + &Aura::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE + &Aura::HandleModMechanicImmunity, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS - &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_RESIST_PUSHBACK + &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK &Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT &Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance @@ -228,7 +228,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK &Aura::HandleUnused, //173 SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell - &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus (by default intellect, dependent from SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT) + &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus &Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus &Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end &Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM @@ -248,8 +248,8 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct) - &Aura::HandleUnused, //194 SPELL_AURA_MOD_DEPRICATED_1 not used now (old SPELL_AURA_MOD_SPELL_DAMAGE_OF_INTELLECT) - &Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT) + &Aura::HandleNoImmediateEffect, //194 SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist + &Aura::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL implemented in Unit::CalcAbsorbResist &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance &Aura::HandleUnused, //198 SPELL_AURA_MOD_ALL_WEAPON_SKILLS @@ -274,23 +274,23 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleUnused, //217 unused &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT - &Aura::HandleNULL, //220 SPELL_AURA_MOD_RATING_FROM_STAT + &Aura::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT &Aura::HandleNULL, //221 ignored - &Aura::HandleUnused, //222 unused + &Aura::HandleNULL, //222 unused &Aura::HandleNULL, //223 Cold Stare &Aura::HandleUnused, //224 unused &Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING &Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY - &Aura::HandleNULL, //227 periodic trigger spell + &Aura::HandlePeriodicTriggerSpellWithValue, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE &Aura::HandleNoImmediateEffect, //228 stealth detection &Aura::HandleNULL, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE - &Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout - &Aura::HandleNULL, //231 + &Aura::HandleAuraModIncreaseHealth, //230 SPELL_AURA_MOD_INCREASE_HEALTH_2 + &Aura::HandleNoImmediateEffect, //231 SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE &Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration &Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue &Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration &Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult - &Aura::HandleUnused, //236 unused + &Aura::HandleAuraControlVehicle, //236 SPELL_AURA_CONTROL_VEHICLE &Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonus &Aura::HandleModSpellHealingPercentFromAttackPower, //238 SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER implemented in Unit::SpellBaseHealingBonus &Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61 @@ -299,31 +299,53 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING &Aura::HandleUnused, //243 used by two test spells &Aura::HandleComprehendLanguage, //244 Comprehend language - &Aura::HandleUnused, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS - &Aura::HandleUnused, //246 unused + &Aura::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL + &Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK implemented in Spell::EffectApplyAura &Aura::HandleUnused, //247 unused &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst - &Aura::HandleNULL, //249 + &Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE &Aura::HandleAuraModIncreaseHealth, //250 SPELL_AURA_MOD_INCREASE_HEALTH_2 - &Aura::HandleNULL, //251 SPELL_AURA_MOD_ENEMY_DODGE - &Aura::HandleUnused, //252 unused - &Aura::HandleUnused, //253 unused - &Aura::HandleUnused, //254 unused - &Aura::HandleUnused, //255 unused - &Aura::HandleUnused, //256 unused - &Aura::HandleUnused, //257 unused - &Aura::HandleUnused, //258 unused - &Aura::HandleUnused, //259 unused - &Aura::HandleUnused, //260 unused - &Aura::HandleNULL //261 SPELL_AURA_261 some phased state (44856 spell) + &Aura::HandleNoImmediateEffect, //251 SPELL_AURA_MOD_ENEMY_DODGE + &Aura::HandleNULL, //252 haste all? + &Aura::HandleNoImmediateEffect, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE implemented in Unit::isBlockCritical + &Aura::HandleAuraModDisarm, //254 SPELL_AURA_MOD_DISARM_OFFHAND + &Aura::HandleNoImmediateEffect, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT implemented in Unit::SpellDamageBonus + &Aura::HandleNoReagentUseAura, //256 SPELL_AURA_NO_REAGENT_USE Use SpellClassMask for spell select + &Aura::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS Use SpellClassMask for spell select + &Aura::HandleNULL, //258 SPELL_AURA_MOD_SPELL_VISUAL + &Aura::HandleNoImmediateEffect, //259 SPELL_AURA_MOD_HOT_PCT implemented in Unit::SpellHealingBonus + &Aura::HandleNoImmediateEffect, //260 SPELL_AURA_SCREEN_EFFECT (miscvalue = id in ScreenEffect.dbc) not required any code + &Aura::HandlePhase, //261 SPELL_AURA_PHASE undetactable invisibility? implemented in Unit::isVisibleForOrDetect + &Aura::HandleNoImmediateEffect, //262 SPELL_AURA_ABILITY_IGNORE_AURASTATE implemented in spell::cancast + &Aura::HandleAuraAllowOnlyAbility, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask + &Aura::HandleNULL, //264 unused + &Aura::HandleNULL, //265 unused + &Aura::HandleNULL, //266 unused + &Aura::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect + &Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT + &Aura::HandleNoImmediateEffect, //269 SPELL_AURA_MOD_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage + &Aura::HandleNoImmediateEffect, //270 SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST implemented in Unit::CalcAbsorbResist and CalcArmorReducedDamage + &Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus + &Aura::HandleNULL, //272 reduce spell cast time? + &Aura::HandleUnused, //273 clientside + &Aura::HandleNoImmediateEffect, //274 SPELL_AURA_CONSUME_NO_AMMO implemented in spell::CalculateDamageDoneForAllTargets + &Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select + &Aura::HandleNULL, //276 mod damage % mechanic? + &Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_ABILITY_AFFECTED_TARGETS implemented in spell::settargetmap + &Aura::HandleAuraModDisarm, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon + &Aura::HandleNULL, //279 + &Aura::HandleNoImmediateEffect, //280 SPELL_AURA_MOD_WEAPONTYPE_IGNORE_TARGET_RESISTANCE + &Aura::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN_PCT implemented in Player::RewardHonor + &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT + &Aura::HandleNoImmediateEffect //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus }; Aura::Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem) : -m_procCharges(0), m_stackAmount(1), m_spellmod(NULL), m_effIndex(eff), m_caster_guid(0), m_target(target), -m_timeCla(1000), m_castItemGuid(castItem?castItem->GetGUID():0), m_auraSlot(MAX_AURAS), -m_positive(false), m_permanent(false), m_isPeriodic(false), m_isTrigger(false), m_isAreaAura(false), -m_isPersistent(false), m_updated(false), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_isRemovedOnShapeLost(true), m_in_use(false), -m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE) +m_spellmod(NULL), m_caster_guid(0), m_castItemGuid(castItem?castItem->GetGUID():0), m_target(target), +m_timeCla(1000), m_periodicTimer(0), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE), +m_effIndex(eff), m_auraSlot(MAX_AURAS), m_auraFlags(AFLAG_NONE), m_auraLevel(1), m_procCharges(0), m_stackAmount(1), +m_positive(false), m_permanent(false), m_isPeriodic(false), m_isAreaAura(false), m_isPersistent(false), +m_updated(false), m_isRemovedOnShapeLost(true), m_in_use(false) { assert(target); @@ -355,14 +377,14 @@ m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE) { m_caster_guid = target->GetGUID(); //damage = m_currentBasePoints+1; // stored value-1 - m_maxduration = target->CalculateSpellDuration(m_spellProto, m_effIndex, target); + m_maxduration = target->CalcSpellDuration(m_spellProto); } else { m_caster_guid = caster->GetGUID(); //damage = caster->CalculateSpellDamage(m_spellProto,m_effIndex,m_currentBasePoints,target); - m_maxduration = caster->CalculateSpellDuration(m_spellProto, m_effIndex, target); + m_maxduration = caster->CalcSpellDuration(m_spellProto); if (!damage && castItem && castItem->GetItemSuffixFactor()) { @@ -399,32 +421,39 @@ m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE) m_duration = m_maxduration; - if(modOwner) - modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_periodicTimer); - sLog.outDebug("Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", m_spellProto->Id, m_spellProto->EffectApplyAuraName[eff], m_maxduration, m_spellProto->EffectImplicitTargetA[eff],damage); m_effIndex = eff; SetModifier(AuraType(m_spellProto->EffectApplyAuraName[eff]), damage, m_spellProto->EffectAmplitude[eff], m_spellProto->EffectMiscValue[eff]); - m_isDeathPersist = IsDeathPersistentSpell(m_spellProto); + // Apply periodic time mod + if(modOwner && m_modifier.periodictime) + modOwner->ApplySpellMod(GetId(), SPELLMOD_ACTIVATION_TIME, m_modifier.periodictime); - if(m_spellProto->procCharges) - { - m_procCharges = m_spellProto->procCharges; + // Start periodic on next tick or at aura apply + if (!(m_spellProto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY)) + m_periodicTimer += m_modifier.periodictime; - if(modOwner) - modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges); - } - else - m_procCharges = -1; + m_isDeathPersist = IsDeathPersistentSpell(m_spellProto); + + m_procCharges = m_spellProto->procCharges; + if(modOwner) + modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges); - m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances && - !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000)); + m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && + m_spellProto->Stances && + !(m_spellProto->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && + !(m_spellProto->Attributes & SPELL_ATTR_NOT_SHAPESHIFT)); } Aura::~Aura() { + //Delete references to aura + if(GetAuraSlot() < MAX_AURAS && m_target && m_target->GetVisibleAura(GetAuraSlot())) + { + AuraSlotEntry * entry = m_target->GetVisibleAura(GetAuraSlot()); + entry->m_slotAuras[GetEffIndex()]=NULL; + } } AreaAura::AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, @@ -446,6 +475,11 @@ Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) m_modifier.m_auraname = SPELL_AURA_NONE; break; + case SPELL_EFFECT_APPLY_AREA_AURA_RAID: + m_areaAuraType = AREA_AURA_RAID; + if(target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isTotem()) + m_modifier.m_auraname = SPELL_AURA_NONE; + break; case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: m_areaAuraType = AREA_AURA_FRIEND; break; @@ -576,28 +610,13 @@ void Aura::Update(uint32 diff) if(m_isPeriodic && (m_duration >= 0 || m_isPassive || m_permanent)) { m_periodicTimer -= diff; - if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N + if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N { - if( m_modifier.m_auraname == SPELL_AURA_MOD_REGEN || - m_modifier.m_auraname == SPELL_AURA_MOD_POWER_REGEN || - // Cannibalize, eating items and other spells - m_modifier.m_auraname == SPELL_AURA_OBS_MOD_HEALTH || - // Eating items and other spells - m_modifier.m_auraname == SPELL_AURA_OBS_MOD_MANA ) - { - ApplyModifier(true); - return; - } // update before applying (aura can be removed in TriggerSpell or PeriodicTick calls) m_periodicTimer += m_modifier.periodictime; if(!m_target->hasUnitState(UNIT_STAT_ISOLATED)) - { - if(m_isTrigger) - TriggerSpell(); - else - PeriodicTick(); - } + PeriodicTick(); } } } @@ -618,17 +637,20 @@ void AreaAura::Update(uint32 diff) case AREA_AURA_PARTY: caster->GetPartyMember(targets, m_radius); break; + case AREA_AURA_RAID: + caster->GetRaidMember(targets, m_radius); + break; case AREA_AURA_FRIEND: { Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(caster, caster, m_radius); - Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(targets, u_check); + Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(caster, targets, u_check); caster->VisitNearbyObject(m_radius, searcher); break; } case AREA_AURA_ENEMY: { Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(caster, caster, m_radius); // No GetCharmer in searcher - Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(targets, u_check); + Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(caster, targets, u_check); caster->VisitNearbyObject(m_radius, searcher); break; } @@ -657,6 +679,7 @@ void AreaAura::Update(uint32 diff) aur = new AreaAura(actualSpellInfo, m_effIndex, &m_modifier.m_amount, (*tIter), caster, NULL); else aur = new AreaAura(actualSpellInfo, m_effIndex, NULL, (*tIter), caster, NULL); + aur->SetAuraDuration(GetAuraDuration()); (*tIter)->AddAura(aur); } } @@ -690,6 +713,11 @@ void AreaAura::Update(uint32 diff) if(!tmp_target->IsInPartyWith(caster)) tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); } + else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me! + { + if(!tmp_target->IsInRaidWith(caster)) + tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); + } else if( m_areaAuraType == AREA_AURA_PET || m_areaAuraType == AREA_AURA_OWNER ) { if( tmp_target->GetGUID() != caster->GetCharmerOrOwnerGUID() ) @@ -740,58 +768,27 @@ void Aura::ApplyModifier(bool apply, bool Real) m_in_use = false; } -void Aura::UpdateAuraDuration() +void Aura::_AddAura() { - if(m_auraSlot >= MAX_AURAS || m_isPassive) + if (!GetId()) return; - - if( m_target->GetTypeId() == TYPEID_PLAYER) - { - WorldPacket data(SMSG_UPDATE_AURA_DURATION, 5); - data << (uint8)m_auraSlot << (uint32)m_duration; - ((Player*)m_target)->SendDirectMessage(&data); - - data.Initialize(SMSG_SET_EXTRA_AURA_INFO, (8+1+4+4+4)); - data.append(m_target->GetPackGUID()); - data << uint8(m_auraSlot); - data << uint32(GetId()); - data << uint32(GetAuraMaxDuration()); - data << uint32(GetAuraDuration()); - ((Player*)m_target)->SendDirectMessage(&data); - } - - // not send in case player loading (will not work anyway until player not added to map), sent in visibility change code - if(m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()) + if(!m_target) return; Unit* caster = GetCaster(); - if(caster && caster->GetTypeId() == TYPEID_PLAYER && caster != m_target) - SendAuraDurationForCaster((Player*)caster); -} - -void Aura::SendAuraDurationForCaster(Player* caster) -{ - WorldPacket data(SMSG_SET_EXTRA_AURA_INFO_NEED_UPDATE, (8+1+4+4+4)); - data.append(m_target->GetPackGUID()); - data << uint8(m_auraSlot); - data << uint32(GetId()); - data << uint32(GetAuraMaxDuration()); // full - data << uint32(GetAuraDuration()); // remain - caster->GetSession()->SendPacket(&data); -} - -void Aura::_AddAura() -{ - if (!GetId()) - return; - if(!m_target) + // passive auras (except totem auras) do not get placed in the slots + // area auras with SPELL_AURA_NONE are not shown on target + // all further code applies only to active spells + if(!((m_spellProto->Attributes & 0x80 || !m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && + (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster))) return; - // we can found aura in NULL_AURA_SLOT and then need store state instead check slot != NULL_AURA_SLOT + // Second aura if some spell bool secondaura = false; + // Try find slot for aura uint8 slot = NULL_AURA_SLOT; - + // Lookup for auras already applied from spell for(uint8 i = 0; i < 3; i++) { Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i); @@ -800,109 +797,97 @@ void Aura::_AddAura() // allow use single slot only by auras from same caster if(itr->second->GetCasterGUID()==GetCasterGUID()) { - secondaura = true; slot = itr->second->GetAuraSlot(); + secondaura = true; break; } } - - if(secondaura) + if (secondaura) break; } + // Lookup free slot + if (!secondaura && m_target->GetVisibleAurasCount() < MAX_AURAS ) + { + Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras(); + for(uint8 i = 0; i < MAX_AURAS; ++i) + { + Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(i); + if(itr == visibleAuras->end()) + { + slot = i; + break; + } + } + } - Unit* caster = GetCaster(); - - // not call total regen auras at adding - switch (m_modifier.m_auraname) + if (!secondaura) { - /*case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_LEECH: - if(caster) - m_modifier.m_amount = caster->SpellDamageBonus(m_target, m_spellProto, m_modifier.m_amount, DOT); - break; - case SPELL_AURA_PERIODIC_HEAL: - if(caster) - m_modifier.m_amount = caster->SpellHealingBonus(m_spellProto, m_modifier.m_amount, DOT, m_target); - break;*/ - case SPELL_AURA_OBS_MOD_HEALTH: - case SPELL_AURA_OBS_MOD_MANA: - m_periodicTimer = m_modifier.periodictime; - break; - case SPELL_AURA_MOD_REGEN: - case SPELL_AURA_MOD_POWER_REGEN: - case SPELL_AURA_MOD_MANA_REGEN_FROM_STAT: - m_periodicTimer = 5000; - break; + AuraSlotEntry t_entry; + t_entry.m_Flags=(IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE); + t_entry.m_Level=(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + + //init pointers-prevent unexpected behaviour + for(uint8 i = 0; i < 3; i++) + t_entry.m_slotAuras[i]=NULL; + + t_entry.m_Level=(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + m_target->SetVisibleAura(slot, t_entry); } - // register aura - if (getDiminishGroup() != DIMINISHING_NONE ) - m_target->ApplyDiminishingAura(getDiminishGroup(),true); + AuraSlotEntry * entry; + entry=m_target->GetVisibleAura(slot); + if(!entry) + return; - // passive auras (except totem auras) do not get placed in the slots - // area auras with SPELL_AURA_NONE are not shown on target - if((!m_isPassive || (caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) && - (m_spellProto->Effect[GetEffIndex()] != SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || m_target != caster)) - { - if(!secondaura) // new slot need - { - if (IsPositive()) // empty positive slot - { - for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++) - { - if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) - { - slot = i; - break; - } - } - } - else // empty negative slot - { - for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++) - { - if (m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + i)) == 0) - { - slot = i; - break; - } - } - } + entry->m_Flags |= (1 << GetEffIndex()); + entry->m_slotAuras[GetEffIndex()]=this; - SetAuraSlot( slot ); + SetAuraSlot( slot ); - // Not update fields for not first spell's aura, all data already in fields - if(slot < MAX_AURAS) // slot found - { - SetAura(slot, false); - SetAuraFlag(slot, true); - SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); - UpdateAuraCharges(); + // update for out of range group members (on 1 slot use) + m_target->UpdateAuraForGroup(slot); - // update for out of range group members - m_target->UpdateAuraForGroup(slot); - } - } - else // use found slot - { - SetAuraSlot( slot ); - } + //***************************************************** + // Update target aura state flag (at 1 aura apply) + // TODO: Make it easer + //***************************************************** + if (!secondaura) + { + // Sitdown on apply aura req seated + if (m_spellProto->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED && !m_target->IsSitState()) + m_target->SetStandState(UNIT_STAND_STATE_SIT); - UpdateSlotCounterAndDuration(); + // register aura diminishing on apply + if (getDiminishGroup() != DIMINISHING_NONE ) + m_target->ApplyDiminishingAura(getDiminishGroup(),true); // Update Seals information - if( IsSealSpell(GetSpellProto()) ) + if (IsSealSpell(m_spellProto)) m_target->ModifyAuraState(AURA_STATE_JUDGEMENT, true); - // Conflagrate aura state - if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) + // Conflagrate aura state on Immolate + if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellProto->SpellFamilyFlags[0] & 4) m_target->ModifyAuraState(AURA_STATE_IMMOLATE, true); - if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) - { + // Faerie Fire (druid versions) + if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x400) + m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE, true); + + // Victorious + if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags[1] & 0x00040000) + m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, true); + + // Swiftmend state on Regrowth & Rejuvenation + if (m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && m_spellProto->SpellFamilyFlags[0] & 0x50 ) m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, true); - } + + // Deadly poison aura state + if(m_spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && m_spellProto->SpellFamilyFlags[0] & 0x10000) + m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON, true); + + // Enrage aura state + if(m_spellProto->Dispel == DISPEL_ENRAGE) + m_target->ModifyAuraState(AURA_STATE_ENRAGE, true); } } @@ -922,10 +907,6 @@ void Aura::_RemoveAura() dynObj->RemoveAffected(m_target); } - // unregister aura - if (getDiminishGroup() != DIMINISHING_NONE ) - m_target->ApplyDiminishingAura(getDiminishGroup(),false); - //passive auras do not get put in slots // Note: but totem can be not accessible for aura target in time remove (to far for find in grid) //if(m_isPassive && !(caster && caster->GetTypeId() == TYPEID_UNIT && ((Creature*)caster)->isTotem())) @@ -936,63 +917,89 @@ void Aura::_RemoveAura() if(slot >= MAX_AURAS) // slot not set return; - if(m_target->GetUInt32Value((uint16)(UNIT_FIELD_AURA + slot)) == 0) + if(!m_target->GetVisibleAura(slot)) //slot already removed-shouldn't happen return; - bool samespell = false; + bool lastaura = true; - // find other aura in same slot (current already removed from list) - for(uint8 i = 0; i < 3; i++) + AuraSlotEntry * entry=m_target->GetVisibleAura(slot); + + entry->m_slotAuras[GetEffIndex()]=NULL; //unregister aura + Aura * ptr= NULL; + for (uint8 i=0 ; i<3; i++) //check slot for more auras of the spell { - Unit::spellEffectPair spair = Unit::spellEffectPair(GetId(), i); - for(Unit::AuraMap::const_iterator itr = m_target->GetAuras().lower_bound(spair); itr != m_target->GetAuras().upper_bound(spair); ++itr) + if (entry->m_slotAuras[i]) { - if(itr->second->GetAuraSlot()==slot) - { - samespell = true; - - break; - } - } - if(samespell) + ptr=entry->m_slotAuras[i]; break; + } } // only remove icon when the last aura of the spell is removed (current aura already removed from list) - if (!samespell) + if(!ptr) { - SetAura(slot, true); - SetAuraFlag(slot, false); - SetAuraLevel(slot,caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + // unregister aura diminishing (and store last time) + if (getDiminishGroup() != DIMINISHING_NONE ) + m_target->ApplyDiminishingAura(getDiminishGroup(),false); - SetAuraApplication(slot, 0); // update for out of range group members m_target->UpdateAuraForGroup(slot); - if( IsSealSpell(GetSpellProto()) ) - m_target->ModifyAuraState(AURA_STATE_JUDGEMENT,false); + //***************************************************** + // Update target aura state flag (at last aura remove) + //***************************************************** + // Enrage aura state + if(m_spellProto->Dispel == DISPEL_ENRAGE) + m_target->ModifyAuraState(AURA_STATE_ENRAGE, false); - // Conflagrate aura state - if (GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 4)) - m_target->ModifyAuraState(AURA_STATE_IMMOLATE, false); + uint32 removeState = 0; + switch(m_spellProto->SpellFamilyName) + { + case SPELLFAMILY_PALADIN: + if (IsSealSpell(m_spellProto)) + removeState = AURA_STATE_JUDGEMENT; // Update Seals information + break; + case SPELLFAMILY_WARLOCK: + if(m_spellProto->SpellFamilyFlags[0] & 4) + removeState = AURA_STATE_IMMOLATE; // Conflagrate aura state + break; + case SPELLFAMILY_DRUID: + if(m_spellProto->SpellFamilyFlags[0] & 0x400) + removeState = AURA_STATE_FAERIE_FIRE; // Faerie Fire (druid versions) + else if(m_spellProto->SpellFamilyFlags[0] & 0x50) + removeState = AURA_STATE_SWIFTMEND; // Swiftmend aura state + break; + case SPELLFAMILY_WARRIOR: + if(m_spellProto->SpellFamilyFlags[1] & 0x00040000) + removeState = AURA_STATE_WARRIOR_VICTORY_RUSH; // Victorious + break; + case SPELLFAMILY_ROGUE: + if(m_spellProto->SpellFamilyFlags[0] & 0x10000) + removeState = AURA_STATE_DEADLY_POISON; // Deadly poison aura state + break; + case SPELLFAMILY_HUNTER: + if(m_spellProto->SpellFamilyFlags[1] & 0x10000000) + removeState = AURA_STATE_FAERIE_FIRE; // Sting (hunter versions) - // Swiftmend aura state - if(GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && (GetSpellProto()->SpellFamilyFlags == 0x40 || GetSpellProto()->SpellFamilyFlags == 0x10)) + } + // Remove state (but need check other auras for it) + if (removeState) { bool found = false; - Unit::AuraList const& RejorRegr = m_target->GetAurasByType(SPELL_AURA_PERIODIC_HEAL); - for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) + Unit::AuraMap& Auras = m_target->GetAuras(); + for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) { - if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) ) + SpellEntry const *auraSpellInfo = (*i).second->GetSpellProto(); + if(auraSpellInfo->SpellFamilyName == m_spellProto->SpellFamilyName && + auraSpellInfo->SpellFamilyFlags == m_spellProto->SpellFamilyFlags ) { found = true; break; } } + // this has been last aura if(!found) - m_target->ModifyAuraState(AURA_STATE_SWIFTMEND, false); + m_target->ModifyAuraState(AuraState(removeState), false); } // reset cooldown state for spells @@ -1004,56 +1011,66 @@ void Aura::_RemoveAura() } } -void Aura::SetAuraFlag(uint32 slot, bool add) +void Aura::SetStackAmount(uint8 stackAmount) { - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAFLAGS + index); - val &= ~((uint32)AFLAG_MASK << byte); - if(add) + if (stackAmount != m_stackAmount) { - if (IsPositive()) - val |= ((uint32)AFLAG_POSITIVE << byte); - else - val |= ((uint32)AFLAG_NEGATIVE << byte); + Unit *target = GetTarget(); + Unit *caster = GetCaster(); + if (!target || !caster) + return; + 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); + } } - m_target->SetUInt32Value(UNIT_FIELD_AURAFLAGS + index, val); + RefreshAura(); } -void Aura::SetAuraLevel(uint32 slot,uint32 level) +bool Aura::modStackAmount(int32 num) { - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURALEVELS + index); - val &= ~(0xFF << byte); - val |= (level << byte); - m_target->SetUInt32Value(UNIT_FIELD_AURALEVELS + index, val); + // Can`t mod + if (!m_spellProto->StackAmount) + return true; + + // Modify stack but limit it + int32 stackAmount = m_stackAmount + num; + if (stackAmount > m_spellProto->StackAmount) + stackAmount = m_spellProto->StackAmount; + else if (stackAmount <=0) // Last aura from stack removed + { + m_stackAmount = 0; + return true; // need remove aura + } + + // Update stack amount + SetStackAmount(stackAmount); + return false; } -void Aura::SetAuraApplication(uint32 slot, int8 count) +void Aura::RefreshAura() { - uint32 index = slot / 4; - uint32 byte = (slot % 4) * 8; - uint32 val = m_target->GetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index); - val &= ~(0xFF << byte); - val |= ((uint8(count)) << byte); - m_target->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS + index, val); + m_duration = m_maxduration; + // update for out of range group members (on 1 slot use) + m_target->UpdateAuraForGroup(GetAuraSlot()); } -void Aura::UpdateSlotCounterAndDuration() +bool Aura::isAffectedOnSpell(SpellEntry const *spell) const { - uint8 slot = GetAuraSlot(); - if(slot >= MAX_AURAS) - return; - - // Three possibilities: - // Charge = 0; Stack >= 0 - // Charge = 1; Stack >= 0 - // Charge > 1; Stack = 0 - if(m_procCharges < 2) - SetAuraApplication(slot, m_stackAmount-1); - - UpdateAuraDuration(); + if (!spell) + return false; + // Check family name + if (spell->SpellFamilyName != m_spellProto->SpellFamilyName) + return false; + // Check EffectClassMask + if (m_spellProto->EffectSpellClassMask[m_effIndex] & spell->SpellFamilyFlags) + return true; + return false; } /*********************************************************/ @@ -1064,10 +1081,6 @@ void Aura::HandleAddModifier(bool apply, bool Real) if(m_target->GetTypeId() != TYPEID_PLAYER || !Real) return; - SpellEntry const *spellInfo = GetSpellProto(); - if(!spellInfo) - return; - if(m_modifier.m_miscvalue >= MAX_SPELLMOD) return; @@ -1078,40 +1091,35 @@ void Aura::HandleAddModifier(bool apply, bool Real) { case 17941: // Shadow Trance case 22008: // Netherwind Focus + case 31834: // Light's Grace + case 34754: // Clearcasting case 34936: // Backlash - m_procCharges = 1; + case 48108: // Hot Streak + case 54741: // Firestarter + case 57761: // Fireball! + SetAuraCharges(1); break; } SpellModifier *mod = new SpellModifier; mod->op = SpellModOp(m_modifier.m_miscvalue); - mod->value = GetModifierValue(); + mod->value = m_modifier.m_amount; mod->type = SpellModType(m_modifier.m_auraname); // SpellModType value == spell aura types mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; - uint64 spellAffectMask = spellmgr.GetSpellAffectMask(GetId(), m_effIndex); - - if (spellAffectMask) - mod->mask = spellAffectMask; - else - mod->mask = spellInfo->EffectItemType[m_effIndex]; - - if (m_procCharges > 0) - mod->charges = m_procCharges; - else - mod->charges = 0; + flag96 const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex); + if (!spellAffect) + spellAffect = &m_spellProto->EffectSpellClassMask[m_effIndex]; + mod->mask = *spellAffect; + mod->charges = m_procCharges; m_spellmod = mod; } - uint64 spellFamilyMask = m_spellmod->mask; - ((Player*)m_target)->AddSpellMod(m_spellmod, apply); // reapply some passive spells after add/remove related spellmods - if(spellInfo->SpellFamilyName==SPELLFAMILY_WARRIOR && (spellFamilyMask & 0x0000100000000000LL)) + if(m_spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && (m_spellmod->mask[1] & 0x00001000)) { m_target->RemoveAurasDueToSpell(45471); @@ -1119,6 +1127,29 @@ void Aura::HandleAddModifier(bool apply, bool Real) m_target->CastSpell(m_target,45471,true); } } +void Aura::HandleAddTargetTrigger(bool apply, bool Real) +{ + // Use SpellModifier structure for check + // used only fields: + // spellId, mask, mask2 + if (apply) + { + SpellModifier *mod = new SpellModifier; + mod->spellId = GetId(); + + flag96 const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex); + if (!spellAffect) + spellAffect = &m_spellProto->EffectSpellClassMask[m_effIndex]; + + mod->mask = *spellAffect; + m_spellmod = mod; + } + else + { + delete m_spellmod; + m_spellmod = NULL; + } +} void Aura::TriggerSpell() { @@ -1131,8 +1162,6 @@ void Aura::TriggerSpell() // generic casting code with custom spells and target/caster customs uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex]; - uint64 originalCasterGUID = GetCasterGUID(); - SpellEntry const *triggeredSpellInfo = sSpellStore.LookupEntry(trigger_spell_id); SpellEntry const *auraSpellInfo = GetSpellProto(); uint32 auraId = auraSpellInfo->Id; @@ -1340,26 +1369,10 @@ void Aura::TriggerSpell() Creature* creature = (Creature*)target; // missing lootid has been reported on startup - just return if (!creature->GetCreatureInfo()->SkinLootId) - { return; - } - Loot *loot = &creature->loot; - loot->clear(); - loot->FillLoot(creature->GetCreatureInfo()->SkinLootId, LootTemplates_Skinning, NULL); - for(uint8 i=0;i<loot->items.size();i++) - { - LootItem *item = loot->LootItemInSlot(i,player); - ItemPosCountVec dest; - uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, item->itemid, item->count ); - if ( msg == EQUIP_ERR_OK ) - { - Item * newitem = player->StoreNewItem( dest, item->itemid, true, item->randomPropertyId); - - player->SendNewItem(newitem, uint32(item->count), false, false, true); - } - else - player->SendEquipError( msg, NULL, NULL ); - } + + player->AutoStoreLoot(creature->GetCreatureInfo()->SkinLootId,LootTemplates_Skinning,true); + creature->setDeathState(JUST_DIED); creature->RemoveCorpse(); creature->SetHealth(0); // just for nice GM-mode view @@ -1729,7 +1742,7 @@ void Aura::TriggerSpell() { SpellEntry const* spell = itr->second->GetSpellProto(); if( spell->SpellFamilyName == SPELLFAMILY_SHAMAN && - spell->SpellFamilyFlags & 0x0000000000000400L) + spell->SpellFamilyFlags[0] & 0x400) return; } target->RemoveAurasDueToSpell(28820); @@ -1799,8 +1812,8 @@ void Aura::TriggerSpell() { switch((*i)->GetModifier()->m_miscvalue) { - case STAT_INTELLECT: intellectLoss += (*i)->GetModifierValue(); break; - case STAT_SPIRIT: spiritLoss += (*i)->GetModifierValue(); break; + case STAT_INTELLECT: intellectLoss += (*i)->GetModifier()->m_amount; break; + case STAT_SPIRIT: spiritLoss += (*i)->GetModifier()->m_amount; break; default: break; } } @@ -1810,20 +1823,19 @@ void Aura::TriggerSpell() return; caster = target; - originalCasterGUID = 0; break; } // Mana Tide case 16191: { - caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this, originalCasterGUID); + caster->CastCustomSpell(target, trigger_spell_id, &m_modifier.m_amount, NULL, NULL, true, NULL, this); return; } } } if(!GetSpellMaxRange(sSpellRangeStore.LookupEntry(triggeredSpellInfo->rangeIndex))) target = m_target; //for druid dispel poison - m_target->CastSpell(target, triggeredSpellInfo, true, 0, this, originalCasterGUID); + m_target->CastSpell(target, triggeredSpellInfo, true, 0, this, GetCasterGUID()); } Unit* Aura::GetTriggerTarget() const @@ -1835,6 +1847,21 @@ Unit* Aura::GetTriggerTarget() const return target ? target : m_target; } +void Aura::TriggerSpellWithValue() +{ + Unit* caster = GetCaster(); + Unit* target = GetTriggerTarget(); + + if(!caster || !target) + return; + + // generic casting code with custom spells and target/caster customs + uint32 trigger_spell_id = GetSpellProto()->EffectTriggerSpell[m_effIndex]; + int32 basepoints0 = this->GetModifier()->m_amount; + + caster->CastCustomSpell(target, trigger_spell_id, &basepoints0, 0, 0, true, 0, this); +} + /*********************************************************/ /*** AURA EFFECTS ***/ /*********************************************************/ @@ -1868,7 +1895,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; case 43873: // Headless Horseman Laugh if(caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)caster)->SendPlaySound(11965, false); + ((Player*)caster)->PlaySound(11965, false); return; case 46354: // Blood Elf Illusion if(caster) @@ -1893,11 +1920,11 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } // Earth Shield - if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags & 0x40000000000LL)) + if ( caster && GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && (GetSpellProto()->SpellFamilyFlags[1] & 0x400)) { // prevent double apply bonuses if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) - m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target); + m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE); return; } } @@ -1964,6 +1991,25 @@ void Aura::HandleAuraDummy(bool apply, bool Real) m_target->SetReducedThreatPercent(0, 0); return; } + + if (caster && m_removeMode == AURA_REMOVE_BY_DEATH) + { + // Stop caster Arcane Missle chanelling on death + if (m_spellProto->SpellFamilyName == SPELLFAMILY_MAGE && + m_spellProto->SpellFamilyFlags[0] & 0x800) + { + caster->InterruptSpell(CURRENT_CHANNELED_SPELL); + return; + } + // Stop caster Penance chanelling on death + if (m_spellProto->SpellFamilyName == SPELLFAMILY_PRIEST && + m_spellProto->SpellFamilyFlags[2] & 0x00000080) + { + caster->InterruptSpell(CURRENT_CHANNELED_SPELL); + return; + } + + } } // AT APPLY & REMOVE @@ -2004,12 +2050,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real) m_target->RemoveAurasDueToSpell(spellId); return; } - // Victorious - if(GetId()==32216 && m_target->getClass()==CLASS_WARRIOR) - { - m_target->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, apply); - return; - } //Summon Fire Elemental if (GetId() == 40133 && caster) { @@ -2042,10 +2082,25 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } case SPELLFAMILY_MAGE: { - // Hypothermia - if( GetId()==41425 ) + break; + } + case SPELLFAMILY_PRIEST: + { + // Pain and Suffering + if( m_spellProto->SpellIconID == 2874 && m_target->GetTypeId()==TYPEID_PLAYER ) { - m_target->ModifyAuraState(AURA_STATE_HYPOTHERMIA,apply); + if(apply) + { + // Reduce backfire damage (dot damage) from Shadow Word: Death + SpellModifier *mod = new SpellModifier; + mod->op = SPELLMOD_DOT; + mod->value = m_modifier.m_amount; + mod->type = SPELLMOD_PCT; + mod->spellId = GetId(); + mod->mask[1] = 0x00000002; + m_spellmod = mod; + } + ((Player*)m_target)->AddSpellMod(m_spellmod, apply); return; } break; @@ -2053,24 +2108,38 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case SPELLFAMILY_DRUID: { // Lifebloom - if ( GetSpellProto()->SpellFamilyFlags & 0x1000000000LL ) + if ( GetSpellProto()->SpellFamilyFlags[1] & 0x10 ) { if ( apply ) { if ( caster ) // prevent double apply bonuses if(m_target->GetTypeId()!=TYPEID_PLAYER || !((Player*)m_target)->GetSession()->PlayerLoading()) - m_modifier.m_amount = caster->SpellHealingBonus(GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE, m_target); + m_modifier.m_amount = caster->SpellHealingBonus(m_target, GetSpellProto(), m_modifier.m_amount, SPELL_DIRECT_DAMAGE); } - // Do final heal for real !apply - else if (Real) + else { - if (GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) + // Final heal only on dispelled or duration end + if ( !(GetAuraDuration() <= 0 || m_removeMode==AURA_REMOVE_BY_DISPEL) ) + return; + + // final heal + if(m_target->IsInWorld()) + m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); + + /*// have a look if there is still some other Lifebloom dummy aura + Unit::AuraList auras = m_target->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::iterator itr = auras.begin(); itr!=auras.end(); ++itr) + if((*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID && + (*itr)->GetSpellProto()->SpellFamilyFlags & 0x1000000000LL) + return; + + // final heal + if(m_target->IsInWorld() && m_stackAmount > 0) { - // final heal - if(m_target->IsInWorld()) - m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); - } + int32 amount = m_modifier.m_amount / m_stackAmount; + m_target->CastCustomSpell(m_target,33778,&amount,NULL,NULL,true,NULL,this,GetCasterGUID()); + }*/ } return; } @@ -2091,10 +2160,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) mod->value = m_modifier.m_amount/7; mod->type = SPELLMOD_FLAT; mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; - mod->mask = 0x001000000000LL; - mod->charges = 0; + mod->mask[1] = 0x0010; m_spellmod = mod; } @@ -2117,10 +2183,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) mod->value = m_modifier.m_amount; mod->type = SPELLMOD_FLAT; mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; - mod->mask = 0x4000000000000LL; - mod->charges = 0; + mod->mask[1] = 0x40000; m_spellmod = mod; } @@ -2142,18 +2205,15 @@ void Aura::HandleAuraDummy(bool apply, bool Real) mod->value = m_modifier.m_amount; mod->type = SPELLMOD_PCT; mod->spellId = GetId(); - mod->effectId = m_effIndex; - mod->lastAffected = NULL; switch (m_effIndex) { case 0: - mod->mask = 0x00200000000LL; // Windfury Totem + mod->mask[1] = 0x002; // Windfury Totem break; case 1: - mod->mask = 0x00400000000LL; // Flametongue Totem + mod->mask[1] = 0x004; // Flametongue Totem break; } - mod->charges = 0; m_spellmod = mod; } @@ -2194,42 +2254,6 @@ void Aura::HandleAuraDummy(bool apply, bool Real) } } -void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) -{ - // spells required only Real aura add/remove - if(!Real) - return; - - SpellEntry const*spell = GetSpellProto(); - switch( spell->SpellFamilyName) - { - case SPELLFAMILY_ROGUE: - { - // Master of Subtlety - if (spell->Id==31666 && !apply && Real) - { - m_target->RemoveAurasDueToSpell(31665); - break; - } - break; - } - case SPELLFAMILY_HUNTER: - { - // Aspect of the Viper - if (spell->SpellFamilyFlags&0x0004000000000000LL) - { - // Update regen on remove - if (!apply && m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->UpdateManaRegen(); - break; - } - break; - } - } - - m_isPeriodic = apply; -} - void Aura::HandleAuraMounted(bool apply, bool Real) { // only at real add/remove aura @@ -2312,12 +2336,8 @@ void Aura::HandleAuraHover(bool apply, bool Real) void Aura::HandleWaterBreathing(bool apply, bool Real) { - if(apply) - m_target->waterbreath = true; - else if(m_target->GetAurasByType(SPELL_AURA_WATER_BREATHING).empty()) + if(!apply && !m_target->HasAuraType(SPELL_AURA_WATER_BREATHING)) { - m_target->waterbreath = false; - // update for enable timer in case not moving target if(m_target->GetTypeId()==TYPEID_PLAYER && m_target->IsInWorld()) { @@ -2395,6 +2415,9 @@ void Aura::HandleAuraModShapeshift(bool apply, bool Real) else modelid = 21244; break; + case FORM_METAMORPHOSIS: + modelid = 25277; + break; case FORM_AMBIENT: case FORM_SHADOW: case FORM_STEALTH: @@ -2742,7 +2765,7 @@ void Aura::HandleAuraModSkill(bool apply, bool Real) return; uint32 prot=GetSpellProto()->EffectMiscValue[m_effIndex]; - int32 points = GetModifierValue(); + int32 points = m_modifier.m_amount; ((Player*)m_target)->ModifySkillBonus(prot,(apply ? points: -points),m_modifier.m_auraname==SPELL_AURA_MOD_SKILL_TALENT); if(prot == SKILL_DEFENSE) @@ -2762,6 +2785,9 @@ void Aura::HandleChannelDeathItem(bool apply, bool Real) //talent will remove the caster's aura->interrupt channel->remove victim aura if(victim->GetHealth() > 0) return; + // Item amount + if (m_modifier.m_amount <= 0) + return; SpellEntry const *spellInfo = GetSpellProto(); if(spellInfo->EffectItemType[m_effIndex] == 0) @@ -2772,16 +2798,22 @@ void Aura::HandleChannelDeathItem(bool apply, bool Real) (victim->getLevel() <= Trinity::XP::GetGrayLevel(caster->getLevel()) || victim->GetTypeId()==TYPEID_UNIT && !((Player*)caster)->isAllowedToLoot((Creature*)victim)) ) return; + //Adding items + uint32 noSpaceForCount = 0; + uint32 count = m_modifier.m_amount; + ItemPosCountVec dest; - uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], 1 ); + uint8 msg = ((Player*)caster)->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, spellInfo->EffectItemType[m_effIndex], count, &noSpaceForCount); if( msg != EQUIP_ERR_OK ) { + count-=noSpaceForCount; ((Player*)caster)->SendEquipError( msg, NULL, NULL ); - return; + if (count==0) + return; } Item* newitem = ((Player*)caster)->StoreNewItem(dest, spellInfo->EffectItemType[m_effIndex], true); - ((Player*)caster)->SendNewItem(newitem, 1, true, false); + ((Player*)caster)->SendNewItem(newitem, count, true, false); } } @@ -2791,10 +2823,7 @@ void Aura::HandleBindSight(bool apply, bool Real) if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; - if (apply) - m_target->AddPlayerToVision((Player*)caster); - else - m_target->RemovePlayerFromVision((Player*)caster); + ((Player*)caster)->SetBindSight(apply ? m_target : NULL); } void Aura::HandleFarSight(bool apply, bool Real) @@ -2803,7 +2832,7 @@ void Aura::HandleFarSight(bool apply, bool Real) if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; - ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); + ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0); } void Aura::HandleAuraTrackCreatures(bool apply, bool Real) @@ -2839,30 +2868,78 @@ void Aura::HandleAuraTrackStealthed(bool apply, bool Real) void Aura::HandleAuraModScale(bool apply, bool Real) { - m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,GetModifierValue(),apply); + m_target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X,m_modifier.m_amount,apply); } -void Aura::HandleModPossess(bool apply, bool Real) +/*void Aura::HandleModPossess(bool apply, bool Real) { if(!Real) return; + if(m_target->getLevel() > m_modifier.m_amount) + return; + + // not possess yourself + if(GetCasterGUID() == m_target->GetGUID()) + return; + Unit* caster = GetCaster(); - if(caster && caster->GetTypeId() == TYPEID_UNIT) - { - HandleModCharm(apply, Real); + if(!caster) return; - } - if(apply) + if( apply ) { - if(m_target->getLevel() > m_modifier.m_amount) - return; + m_target->SetCharmerGUID(GetCasterGUID()); + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction()); + caster->SetCharm(m_target); - m_target->SetCharmedOrPossessedBy(caster, true); + m_target->CombatStop(); + m_target->DeleteThreatList(); + if(m_target->GetTypeId() == TYPEID_UNIT) + { + m_target->StopMoving(); + m_target->GetMotionMaster()->Clear(); + m_target->GetMotionMaster()->MoveIdle(); + CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target); + charmInfo->InitPossessCreateSpells(); + } + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)caster)->PossessSpellInitialize(); + } } else - m_target->RemoveCharmedOrPossessedBy(caster); + { + m_target->SetCharmerGUID(0); + + if(m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->setFactionForRace(m_target->getRace()); + else if(m_target->GetTypeId() == TYPEID_UNIT) + { + CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A); + } + + caster->SetCharm(0); + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_PET_SPELLS, 8); + data << uint64(0); + data << uint32(0); + ((Player*)caster)->GetSession()->SendPacket(&data); + } + if(m_target->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)m_target)->AIM_Initialize(); + + if (((Creature*)m_target)->AI()) + ((Creature*)m_target)->AI()->AttackStart(caster); + } + } + if(caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)caster)->SetFarSightGUID(apply ? m_target->GetGUID() : 0); } void Aura::HandleModPossessPet(bool apply, bool Real) @@ -2873,42 +2950,151 @@ void Aura::HandleModPossessPet(bool apply, bool Real) Unit* caster = GetCaster(); if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; - if(caster->GetPet() != m_target) + + Pet *pet = caster->GetPet(); + if(!pet || pet != m_target) return; if(apply) - m_target->SetCharmedOrPossessedBy(caster, true); + pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); else - { - m_target->RemoveCharmedOrPossessedBy(caster); + pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); - // Reinitialize the pet bar and make the pet come back to the owner - ((Player*)caster)->PetSpellInitialize(); - if(!m_target->getVictim()) - { - m_target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - m_target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); - } + ((Player*)caster)->SetFarSightGUID(apply ? pet->GetGUID() : NULL); + ((Player*)caster)->SetCharm(apply ? pet : NULL); + ((Player*)caster)->SetClientControl(pet, apply ? 1 : 0); + + if(apply) + { + pet->StopMoving(); + pet->GetMotionMaster()->Clear(); + pet->GetMotionMaster()->MoveIdle(); + } + else + { + pet->AttackStop(); + pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + pet->SetUnitMovementFlags(MOVEMENTFLAG_NONE); } +}*/ + +void Aura::HandleAuraModPetTalentsPoints(bool Apply, bool Real) +{ + if(!Real) + return; + + // Recalculate pet tlaent points + if (Pet *pet=m_target->GetPet()) + pet->InitTalentForLevel(); } -void Aura::HandleModCharm(bool apply, bool Real) +/*void Aura::HandleModCharm(bool apply, bool Real) { if(!Real) return; + // not charm yourself + if(GetCasterGUID() == m_target->GetGUID()) + return; + Unit* caster = GetCaster(); + if(!caster) + return; - if(apply) + if(int32(m_target->getLevel()) <= m_modifier.m_amount) { - if(int32(m_target->getLevel()) > m_modifier.m_amount) - return; + if( apply ) + { + m_target->SetCharmerGUID(GetCasterGUID()); + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,caster->getFaction()); + m_target->CastStop(m_target==caster ? GetId() : 0); + caster->SetCharm(m_target); - m_target->SetCharmedOrPossessedBy(caster, false); + m_target->CombatStop(); + m_target->DeleteThreatList(); + + if(m_target->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)m_target)->AIM_Initialize(); + CharmInfo *charmInfo = ((Creature*)m_target)->InitCharmInfo(m_target); + charmInfo->InitCharmCreateSpells(); + charmInfo->SetReactState( REACT_DEFENSIVE ); + + if(caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK) + { + CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); + if(cinfo && cinfo->type == CREATURE_TYPE_DEMON) + { + //to prevent client crash + m_target->SetFlag(UNIT_FIELD_BYTES_0, 2048); + //just to enable stat window + charmInfo->SetPetNumber(objmgr.GeneratePetNumber(), true); + //if charmed two demons the same session, the 2nd gets the 1st one's name + m_target->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, time(NULL)); + } + } + } + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)caster)->CharmSpellInitialize(); + } + } + else + { + m_target->SetCharmerGUID(0); + + if(m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->setFactionForRace(m_target->getRace()); + else + { + CreatureInfo const *cinfo = ((Creature*)m_target)->GetCreatureInfo(); + + // restore faction + if(((Creature*)m_target)->isPet()) + { + if(Unit* owner = m_target->GetOwner()) + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,owner->getFaction()); + else if(cinfo) + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A); + } + else if(cinfo) // normal creature + m_target->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,cinfo->faction_A); + + // restore UNIT_FIELD_BYTES_0 + if(cinfo && caster->GetTypeId() == TYPEID_PLAYER && caster->getClass() == CLASS_WARLOCK && cinfo->type == CREATURE_TYPE_DEMON) + { + CreatureDataAddon const *cainfo = ((Creature*)m_target)->GetCreatureAddon(); + if(cainfo && cainfo->bytes0 != 0) + m_target->SetUInt32Value(UNIT_FIELD_BYTES_0, cainfo->bytes0); + else + m_target->RemoveFlag(UNIT_FIELD_BYTES_0, 2048); + + if(m_target->GetCharmInfo()) + m_target->GetCharmInfo()->SetPetNumber(0, true); + else + sLog.outError("Aura::HandleModCharm: target="I64FMTD" with typeid=%d has a charm aura but no charm info!", m_target->GetGUID(), m_target->GetTypeId()); + } + } + + caster->SetCharm(0); + + if(caster->GetTypeId() == TYPEID_PLAYER) + { + WorldPacket data(SMSG_PET_SPELLS, 8); + data << uint64(0); + data << uint32(0); + ((Player*)caster)->GetSession()->SendPacket(&data); + } + if(m_target->GetTypeId() == TYPEID_UNIT) + { + ((Creature*)m_target)->AIM_Initialize(); + if (((Creature*)m_target)->AI()) + ((Creature*)m_target)->AI()->AttackStart(caster); + } + } } - else - m_target->RemoveCharmedOrPossessedBy(caster); -} +}*/ void Aura::HandleModConfuse(bool apply, bool Real) { @@ -2947,7 +3133,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real) std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_target, m_target, World::GetMaxVisibleDistance()); - Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(targets, u_check); + Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(m_target, targets, u_check); m_target->VisitNearbyObject(World::GetMaxVisibleDistance(), searcher); for(std::list<Unit*>::iterator iter = targets.begin(); iter != targets.end(); ++iter) { @@ -2964,7 +3150,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real) } } // blizz like 2.0.x - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); + m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); // blizz like 2.0.x m_target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); // blizz like 2.0.x @@ -2989,7 +3175,7 @@ void Aura::HandleFeignDeath(bool apply, bool Real) m_target->SendMessageToSet(&data,true); */ // blizz like 2.0.x - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN6); + m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); // blizz like 2.0.x m_target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); // blizz like 2.0.x @@ -3001,37 +3187,52 @@ void Aura::HandleFeignDeath(bool apply, bool Real) void Aura::HandleAuraModDisarm(bool apply, bool Real) { - if(!Real) + if (!Real) return; + AuraType type = GetModifier()->m_auraname; - if(!apply && m_target->HasAuraType(SPELL_AURA_MOD_DISARM)) + //Prevent handling aura twice + if(apply && m_target->GetAurasByType(type).size()>1) return; - - // not sure for it's correctness + if(!apply && m_target->HasAuraType(type)) + return; + uint32 field, flag, slot; + WeaponAttackType attType; + switch (type) + { + case SPELL_AURA_MOD_DISARM: + field=UNIT_FIELD_FLAGS; + flag=UNIT_FLAG_DISARMED; + slot=EQUIPMENT_SLOT_MAINHAND; + attType=BASE_ATTACK; + break; + case SPELL_AURA_MOD_DISARM_OFFHAND: + field=UNIT_FIELD_FLAGS_2; + flag=UNIT_FLAG2_DISARM_OFFHAND; + slot=EQUIPMENT_SLOT_OFFHAND; + attType=OFF_ATTACK; + break; + case SPELL_AURA_MOD_DISARM_RANGED: + field=UNIT_FIELD_FLAGS_2; + flag=UNIT_FLAG2_DISARM_RANGED; + slot=EQUIPMENT_SLOT_RANGED; + attType=RANGED_ATTACK; + break; + } if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); + m_target->SetFlag(field, flag); else - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); + m_target->RemoveFlag(field, flag); if (m_target->GetTypeId() == TYPEID_PLAYER) { - // main-hand attack speed already set to special value for feral form already and don't must change and reset at remove. - if (((Player *)m_target)->IsInFeralForm()) - return; - - if (apply) - m_target->SetAttackTime(BASE_ATTACK,BASE_ATTACK_TIME); - else - ((Player *)m_target)->SetRegularAttackTime(); - } - else - { - // creature does not have equipment - if(apply && !((Creature*)m_target)->GetCurrentEquipmentId()) + Item *pItem = ((Player*)m_target)->GetItemByPos( INVENTORY_SLOT_BAG_0, slot ); + if(!pItem ) return; + ((Player*)m_target)->_ApplyItemMods(pItem, slot, !apply); } - - m_target->UpdateDamagePhysical(BASE_ATTACK); + else if (((Creature*)m_target)->GetCurrentEquipmentId()) + m_target->UpdateDamagePhysical(attType); } void Aura::HandleAuraModStun(bool apply, bool Real) @@ -3059,7 +3260,7 @@ void Aura::HandleModStealth(bool apply, bool Real) // only at real aura add if(Real) { - m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x02); + m_target->SetStandFlags(UNIT_STAND_FLAGS_CREEP); if(m_target->GetTypeId()==TYPEID_PLAYER) m_target->SetFlag(PLAYER_FIELD_BYTES2, 0x2000); @@ -3070,10 +3271,6 @@ void Aura::HandleModStealth(bool apply, bool Real) //m_target->SetVisibility(VISIBILITY_OFF); m_target->SetVisibility(VISIBILITY_GROUP_STEALTH); } - - // for RACE_NIGHTELF stealth - if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580) - m_target->CastSpell(m_target, 21009, true, NULL, this); } } else @@ -3081,14 +3278,10 @@ void Aura::HandleModStealth(bool apply, bool Real) // only at real aura remove if(Real) { - // for RACE_NIGHTELF stealth - if(m_target->GetTypeId()==TYPEID_PLAYER && GetId()==20580) - m_target->RemoveAurasDueToSpell(21009); - // if last SPELL_AURA_MOD_STEALTH and no GM invisibility if(!m_target->HasAuraType(SPELL_AURA_MOD_STEALTH) && m_target->GetVisibility()!=VISIBILITY_OFF) { - m_target->SetByteValue(UNIT_FIELD_BYTES_1, 2, 0x00); + m_target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP); if(m_target->GetTypeId()==TYPEID_PLAYER) m_target->RemoveFlag(PLAYER_FIELD_BYTES2, 0x2000); @@ -3210,6 +3403,10 @@ void Aura::HandleAuraModRoot(bool apply, bool Real) if(!Real) return; + // Frost root aura -> freeze/unfreeze target + if (GetSpellSchoolMask(m_spellProto) & SPELL_SCHOOL_MASK_FROST) + m_target->ModifyAuraState(AURA_STATE_FROZEN, apply); + m_target->SetControlled(apply, UNIT_STAT_ROOT); } @@ -3249,7 +3446,7 @@ void Aura::HandleAuraModSilence(bool apply, bool Real) return; // Search Mana Tap auras on caster - Aura * dummy = m_target->GetDummyAura(28734); + Aura * dummy = caster->GetDummyAura(28734); if (dummy) { int32 bp = dummy->GetStackAmount() * 10; @@ -3306,7 +3503,7 @@ void Aura::HandleModThreat(bool apply, bool Real) if(m_modifier.m_miscvalue & int32(1<<x)) { if(m_target->GetTypeId() == TYPEID_PLAYER) - ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? GetModifierValue() : -GetModifierValue(), apply); + ApplyPercentModFloatVar(m_target->m_threatModifier[x], m_positive ? m_modifier.m_amount : -m_modifier.m_amount, apply); } } } @@ -3327,9 +3524,9 @@ void Aura::HandleAuraModTotalThreat(bool apply, bool Real) float threatMod = 0.0f; if(apply) - threatMod = float(GetModifierValue()); + threatMod = float(m_modifier.m_amount); else - threatMod = float(-GetModifierValue()); + threatMod = float(-m_modifier.m_amount); m_target->getHostilRefManager().threatAssist(caster, threatMod); } @@ -3398,7 +3595,7 @@ void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real) //Players on flying mounts must be immune to polymorph if (m_target->GetTypeId()==TYPEID_PLAYER) - m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,MECHANIC_POLYMORPH,apply); + m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,1<<MECHANIC_POLYMORPH,apply); // Dragonmaw Illusion (overwrite mount model, mounted aura already applied) if( apply && m_target->HasAura(42016,0) && m_target->GetMountID()) @@ -3445,8 +3642,11 @@ void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real) void Aura::HandleModMechanicImmunity(bool apply, bool Real) { - uint32 mechanic = 1 << m_modifier.m_miscvalue; - + uint32 mechanic; + if (GetSpellProto()->EffectApplyAuraName[GetEffIndex()]==SPELL_AURA_MECHANIC_IMMUNITY) + mechanic = 1 << m_modifier.m_miscvalue; + else //SPELL_AURA_MECHANIC_IMMUNITY_MASK + mechanic = m_modifier.m_miscvalue; //immune movement impairment and loss of control if(GetId()==42292) mechanic=IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK; @@ -3459,9 +3659,8 @@ void Aura::HandleModMechanicImmunity(bool apply, bool Real) next = iter; ++next; SpellEntry const *spell = iter->second->GetSpellProto(); - if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) // spells unaffected by invulnerability - && !iter->second->IsPositive() // only remove negative spells - && spell->Id != GetId()) + if (!( spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) && // spells unaffected by invulnerability + spell->Id != GetId()) { //check for mechanic mask if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & mechanic) @@ -3476,18 +3675,7 @@ void Aura::HandleModMechanicImmunity(bool apply, bool Real) } } - m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,m_modifier.m_miscvalue,apply); - - // special cases - switch(m_modifier.m_miscvalue) - { - case MECHANIC_INVULNERABILITY: - m_target->ModifyAuraState(AURA_STATE_FORBEARANCE,apply); - break; - case MECHANIC_SHIELD: - m_target->ModifyAuraState(AURA_STATE_WEAKENED_SOUL,apply); - break; - } + m_target->ApplySpellImmune(GetId(),IMMUNITY_MECHANIC,mechanic,apply); // Bestial Wrath if ( GetSpellProto()->SpellFamilyName == SPELLFAMILY_HUNTER && GetSpellProto()->Id == 19574) @@ -3662,8 +3850,7 @@ void Aura::HandleAuraProcTriggerSpell(bool apply, bool Real) switch (GetId()) { case 28200: // Ascendance (Talisman of Ascendance trinket) - m_procCharges = 6; - UpdateAuraCharges(); + SetAuraCharges(6); break; default: break; } @@ -3685,75 +3872,72 @@ void Aura::HandleAuraModStalked(bool apply, bool Real) void Aura::HandlePeriodicTriggerSpell(bool apply, bool Real) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - m_isPeriodic = apply; - m_isTrigger = apply; +} - // Curse of the Plaguebringer - if (!apply && m_spellProto->Id == 29213 && m_removeMode!=AURA_REMOVE_BY_DISPEL) - { - // Cast Wrath of the Plaguebringer if not dispelled - m_target->CastSpell(m_target, 29214, true, 0, this); - } +void Aura::HandlePeriodicTriggerSpellWithValue(bool apply, bool Real) +{ + m_isPeriodic = apply; } void Aura::HandlePeriodicEnergize(bool apply, bool Real) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; + if (!Real) + return; m_isPeriodic = apply; + + // Replenishment (0.25% from max) + // Infinite Replenishment + if (GetId() == 57669 || + GetId() == 61782) + m_modifier.m_amount = m_target->GetMaxPower(POWER_MANA) * 25 / 10000; } -void Aura::HandlePeriodicHeal(bool apply, bool Real) +void Aura::HandleAuraPowerBurn(bool apply, bool Real) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - m_isPeriodic = apply; +} - // only at real apply - if (Real && apply && GetSpellProto()->Mechanic == MECHANIC_BANDAGE) - { - // provided m_target as original caster to prevent apply aura caster selection for this negative buff - m_target->CastSpell(m_target,11196,true,NULL,this,m_target->GetGUID()); - } +void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; // For prevent double apply bonuses bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()); - if(!loading && apply) + Unit* caster = GetCaster(); + + SpellEntry const*spell = GetSpellProto(); + switch( spell->SpellFamilyName) { - switch (m_spellProto->SpellFamilyName) + case SPELLFAMILY_ROGUE: { - case SPELLFAMILY_DRUID: + // Master of Subtlety + if (spell->Id==31666 && !apply) { - // Rejuvenation - if(m_spellProto->SpellFamilyFlags & 0x0000000000000010LL) - { - if(Unit* caster = GetCaster()) - { - Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k) - { - int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex]; - switch((*k)->GetModifier()->m_miscvalue) - { - case 4953: // Increased Rejuvenation Healing - Harold's Rejuvenating Broach Aura - case 4415: // Increased Rejuvenation Healing - Idol of Rejuvenation Aura - { - m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount; - break; - } - } - } - } - } + m_target->RemoveAurasDueToSpell(31665); + break; } + break; + } + case SPELLFAMILY_HUNTER: + { + // Explosive Shot + if (apply && !loading && caster) + m_modifier.m_amount +=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100; + break; } } + + m_isPeriodic = apply; +} + +void Aura::HandlePeriodicHeal(bool apply, bool Real) +{ + m_isPeriodic = apply; } void Aura::HandlePeriodicDamage(bool apply, bool Real) @@ -3762,26 +3946,28 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) if(!Real) return; - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - m_isPeriodic = apply; // For prevent double apply bonuses bool loading = (m_target->GetTypeId() == TYPEID_PLAYER && ((Player*)m_target)->GetSession()->PlayerLoading()); + // Custom damage calculation after + if (!apply || loading) + return; + Unit *caster = GetCaster(); + if (!caster) + return; switch (m_spellProto->SpellFamilyName) { case SPELLFAMILY_GENERIC: { // Pounce Bleed - if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual == 0 ) + if ( m_spellProto->SpellIconID == 147 && m_spellProto->SpellVisual[0] == 0 ) { // $AP*0.18/6 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); return; } break; @@ -3789,18 +3975,14 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) case SPELLFAMILY_WARRIOR: { // Rend - if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) + if (m_spellProto->SpellFamilyFlags[0] & 0x20) { - // 0.00743*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick - if (apply && !loading && caster) - { - float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); - int32 mws = caster->GetAttackTime(BASE_ATTACK); - float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE); - float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE); - // WARNING! in 3.0 multiplier 0.00743f change to 0.6 - m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.00743f); - } + // $0.2*(($MWB+$mwb)/2+$AP/14*$MWS) bonus per tick + float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 mws = caster->GetAttackTime(BASE_ATTACK); + float mwb_min = caster->GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE); + float mwb_max = caster->GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE); + m_modifier.m_amount+=int32(((mwb_min+mwb_max)/2+ap*mws/14000)*0.2f); return; } break; @@ -3808,92 +3990,80 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) case SPELLFAMILY_DRUID: { // Rake - if (m_spellProto->SpellFamilyFlags & 0x0000000000001000LL) + if (m_spellProto->SpellFamilyFlags[0] & 0x1000) { - // $AP*0.06/3 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 / 100); + // $AP*0.06 bonus per tick + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 6 / 100); return; } // Lacerate - if (m_spellProto->SpellFamilyFlags & 0x000000010000000000LL) + if (m_spellProto->SpellFamilyFlags[1] & 0x0000000100) { // $AP*0.05/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); return; } // Rip - if (m_spellProto->SpellFamilyFlags & 0x000000000000800000LL) + if (m_spellProto->SpellFamilyFlags[1] & 0x800000) { - // $AP * min(0.06*$cp, 0.24)/6 [Yes, there is no difference, whether 4 or 5 CPs are being used] - if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER) - { - uint8 cp = ((Player*)caster)->GetComboPoints(); + // 0.01*$AP*cp + if (caster->GetTypeId() != TYPEID_PLAYER) + return; + + uint8 cp = ((Player*)caster)->GetComboPoints(); - // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs - Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) + // Idol of Feral Shadows. Cant be handled as SpellMod in SpellAura:Dummy due its dependency from CPs + Unit::AuraList const& dummyAuras = caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) + { + if((*itr)->GetId()==34241) { - if((*itr)->GetId()==34241) - { - m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount; - break; - } + m_modifier.m_amount += cp * (*itr)->GetModifier()->m_amount; + break; } - - if (cp > 4) cp = 4; - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); } + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); + return; + } + // Lock Jaw + if (m_spellProto->SpellFamilyFlags[1] & 0x10000000) + { + // 0.15*$AP + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 15 / 100); return; } break; } case SPELLFAMILY_ROGUE: { - // Deadly poison aura state - if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual==5100) + // Rupture + if (m_spellProto->SpellFamilyFlags[0] & 0x100000) { - if(apply) - m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true); - else - { - // current aura already removed, search present of another - bool found = false; - Unit::AuraList const& auras = m_target->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr != auras.end(); ++itr) - { - SpellEntry const* itr_spell = (*itr)->GetSpellProto(); - if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual==5100) - { - found = true; - break; - } - } - // this has been last deadly poison aura - if(!found) - m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,false); - } + if (caster->GetTypeId() != TYPEID_PLAYER) + return; + //1 point : ${($m1+$b1*1+0.015*$AP)*4} damage over 8 secs + //2 points: ${($m1+$b1*2+0.024*$AP)*5} damage over 10 secs + //3 points: ${($m1+$b1*3+0.03*$AP)*6} damage over 12 secs + //4 points: ${($m1+$b1*4+0.03428571*$AP)*7} damage over 14 secs + //5 points: ${($m1+$b1*5+0.0375*$AP)*8} damage over 16 secs + float AP_per_combo[] = {0, 0.015f, 0.024, 0.03, 0.03428571, 0.0375}; + uint8 cp = ((Player*)caster)->GetComboPoints(); + if (cp > 5) cp = 5; + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * AP_per_combo[cp]); return; } - // Rupture - if (m_spellProto->SpellFamilyFlags & 0x000000000000100000LL) + // Garrote + if (m_spellProto->SpellFamilyFlags[0] & 0x100) { - // Dmg/tick = $AP*min(0.01*$cp, 0.03) [Like Rip: only the first three CP increase the contribution from AP] - if (apply && !loading && caster && caster->GetTypeId() == TYPEID_PLAYER) - { - uint8 cp = ((Player*)caster)->GetComboPoints(); - if (cp > 3) cp = 3; - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * cp / 100); - } + // $AP*0.07 bonus per tick + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 7 / 100); return; } - // Garrote - if (m_spellProto->SpellFamilyFlags & 0x000000000000000100LL) + // Deadly Poison + if (m_spellProto->SpellFamilyFlags[0] & 0x10000) { - // $AP*0.18/6 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 3 / 100); + // 0.08*$AP / 4 * amount of stack + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 2 * GetStackAmount() / 100); return; } break; @@ -3901,47 +4071,17 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) case SPELLFAMILY_HUNTER: { // Serpent Sting - if (m_spellProto->SpellFamilyFlags & 0x0000000000004000LL) + if (m_spellProto->SpellFamilyFlags[0] & 0x4000) { // $RAP*0.1/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); return; } // Immolation Trap - if (m_spellProto->SpellFamilyFlags & 0x0000000000000004LL && m_spellProto->SpellIconID == 678) + if (m_spellProto->SpellFamilyFlags[0] & 0x4 && m_spellProto->SpellIconID == 678) { // $RAP*0.1/5 bonus per tick - if (apply && !loading && caster) - m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); - return; - } - break; - } - case SPELLFAMILY_PALADIN: - { - // Consecration - if (m_spellProto->SpellFamilyFlags & 0x0000000000000020LL) - { - if (apply && !loading) - { - if(Unit* caster = GetCaster()) - { - Unit::AuraList const& classScripts = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator k = classScripts.begin(); k != classScripts.end(); ++k) - { - int32 tickcount = GetSpellDuration(m_spellProto) / m_spellProto->EffectAmplitude[m_effIndex]; - switch((*k)->GetModifier()->m_miscvalue) - { - case 5147: // Improved Consecration - Libram of the Eternal Rest - { - m_modifier.m_amount += (*k)->GetModifier()->m_amount / tickcount; - break; - } - } - } - } - } + m_modifier.m_amount += int32(caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 10 / 500); return; } break; @@ -3953,25 +4093,21 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) void Aura::HandlePeriodicDamagePCT(bool apply, bool Real) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - m_isPeriodic = apply; } void Aura::HandlePeriodicLeech(bool apply, bool Real) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - m_isPeriodic = apply; } void Aura::HandlePeriodicManaLeech(bool apply, bool Real) { - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; + m_isPeriodic = apply; +} +void Aura::HandlePeriodicHealthFunnel(bool apply, bool Real) +{ m_isPeriodic = apply; } @@ -3989,9 +4125,9 @@ void Aura::HandleAuraModResistanceExclusive(bool apply, bool Real) { if(m_modifier.m_miscvalue & int32(1<<x)) { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_VALUE, float(m_modifier.m_amount), apply); if(m_target->GetTypeId() == TYPEID_PLAYER) - m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,GetModifierValue(), apply); + m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply); } } } @@ -4002,19 +4138,11 @@ void Aura::HandleAuraModResistance(bool apply, bool Real) { if(m_modifier.m_miscvalue & int32(1<<x)) { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), TOTAL_VALUE, float(m_modifier.m_amount), apply); if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,GetModifierValue(), apply); + m_target->ApplyResistanceBuffModsMod(SpellSchools(x),m_positive,m_modifier.m_amount, apply); } } - - // Faerie Fire (druid versions) - if( m_spellProto->SpellIconID == 109 && - m_spellProto->SpellFamilyName == SPELLFAMILY_DRUID && - m_spellProto->SpellFamilyFlags & 0x0000000000000400LL ) - { - m_target->ModifyAuraState(AURA_STATE_FAERIE_FIRE,apply); - } } void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real) @@ -4024,14 +4152,14 @@ void Aura::HandleAuraModBaseResistancePCT(bool apply, bool Real) { //pets only have base armor if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) - m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_ARMOR, BASE_PCT, float(m_modifier.m_amount), apply); } else { for(int8 x = SPELL_SCHOOL_NORMAL; x < MAX_SPELL_SCHOOL;x++) { if(m_modifier.m_miscvalue & int32(1<<x)) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + x), BASE_PCT, float(m_modifier.m_amount), apply); } } } @@ -4042,11 +4170,11 @@ void Aura::HandleModResistancePercent(bool apply, bool Real) { if(m_modifier.m_miscvalue & int32(1<<i)) { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply); if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) { - m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,GetModifierValue(), apply); - m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,GetModifierValue(), apply); + m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),true,m_modifier.m_amount, apply); + m_target->ApplyResistanceBuffModsPercentMod(SpellSchools(i),false,m_modifier.m_amount, apply); } } } @@ -4059,13 +4187,13 @@ void Aura::HandleModBaseResistance(bool apply, bool Real) { //only pets have base stats if(((Creature*)m_target)->isPet() && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) - m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_ARMOR, TOTAL_VALUE, float(m_modifier.m_amount), apply); } else { for(int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) if(m_modifier.m_miscvalue & (1<<i)) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply); } } @@ -4087,9 +4215,9 @@ void Aura::HandleAuraModStat(bool apply, bool Real) if (m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue == i) { //m_target->ApplyStatMod(Stats(i), m_modifier.m_amount,apply); - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_VALUE, float(m_modifier.m_amount), apply); if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyStatBuffMod(Stats(i),GetModifierValue(),apply); + m_target->ApplyStatBuffMod(Stats(i),m_modifier.m_amount,apply); } } } @@ -4109,7 +4237,7 @@ void Aura::HandleModPercentStat(bool apply, bool Real) for (int32 i = STAT_STRENGTH; i < MAX_STATS; ++i) { if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), BASE_PCT, float(m_modifier.m_amount), apply); } } @@ -4187,9 +4315,9 @@ void Aura::HandleModTotalPercentStat(bool apply, bool Real) { if(m_modifier.m_miscvalue == i || m_modifier.m_miscvalue == -1) { - m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UnitMods(UNIT_MOD_STAT_START + i), TOTAL_PCT, float(m_modifier.m_amount), apply); if(m_target->GetTypeId() == TYPEID_PLAYER || ((Creature*)m_target)->isPet()) - m_target->ApplyStatPercentBuffMod(Stats(i), GetModifierValue(), apply ); + m_target->ApplyStatPercentBuffMod(Stats(i), m_modifier.m_amount, apply ); } } @@ -4224,117 +4352,47 @@ void Aura::HandleAuraModResistenceOfStatPercent(bool /*apply*/, bool Real) /********************************/ void Aura::HandleAuraModTotalHealthPercentRegen(bool apply, bool Real) { - /* - Need additional checking for auras who reduce or increase healing, magic effect like Dumpen Magic, - so this aura not fully working. - */ - if(apply) - { - if(!m_target->isAlive()) - return; - - if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); - - if(m_periodicTimer <= 0) - { - m_periodicTimer += m_modifier.periodictime; - - if(m_target->GetHealth() < m_target->GetMaxHealth()) - { - // PeriodicTick can cast triggered spells with stats changes - PeriodicTick(); - } - } - } - m_isPeriodic = apply; } void Aura::HandleAuraModTotalManaPercentRegen(bool apply, bool Real) { - if((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); - if(apply) - { - if(m_modifier.periodictime == 0) - m_modifier.periodictime = 1000; - if(m_periodicTimer <= 0 && m_target->getPowerType() == POWER_MANA) - { - m_periodicTimer += m_modifier.periodictime; - - if(m_target->GetPower(POWER_MANA) < m_target->GetMaxPower(POWER_MANA)) - { - // PeriodicTick can cast triggered spells with stats changes - PeriodicTick(); - } - } - } + if(m_modifier.periodictime == 0) + m_modifier.periodictime = 1000; + m_periodicTimer = m_modifier.periodictime; m_isPeriodic = apply; } void Aura::HandleModRegen(bool apply, bool Real) // eating { - if(apply) - { - if(!m_target->isAlive()) - return; - - if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); - - if(m_periodicTimer <= 0) - { - m_periodicTimer += 5000; - int32 gain = m_target->ModifyHealth(GetModifierValue()); - Unit *caster = GetCaster(); - if (caster) - { - SpellEntry const *spellProto = GetSpellProto(); - if (spellProto) - m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, spellProto); - } - } - } + if(m_modifier.periodictime == 0) + m_modifier.periodictime = 5000; + m_periodicTimer = 5000; m_isPeriodic = apply; } void Aura::HandleModPowerRegen(bool apply, bool Real) // drinking { - if ((GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) && apply && !m_target->IsSitState()) - m_target->SetStandState(PLAYER_STATE_SIT); + if (!Real) + return; - if(apply && m_periodicTimer <= 0) + Powers pt = m_target->getPowerType(); + if(m_modifier.periodictime == 0) { - m_periodicTimer += 2000; + if (pt == POWER_RAGE) + m_modifier.periodictime = 1000; + else + m_modifier.periodictime = 2000; + } - Powers pt = m_target->getPowerType(); - if(int32(pt) != m_modifier.m_miscvalue) - return; + m_periodicTimer = 5000; - if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED ) - { - // eating anim - m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT); - } - else if( GetId() == 20577 ) - { - // cannibalize anim - m_target->HandleEmoteCommand(398); - } + if (m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA) + ((Player*)m_target)->UpdateManaRegen(); - // Warrior talent, gain 1 rage every 3 seconds while in combat - if(pt == POWER_RAGE && m_target->isInCombat()) - { - m_target->ModifyPower(pt, m_modifier.m_amount*10/17); - m_periodicTimer += 1000; - } - } m_isPeriodic = apply; - if (Real && m_target->GetTypeId() == TYPEID_PLAYER && m_modifier.m_miscvalue == POWER_MANA) - ((Player*)m_target)->UpdateManaRegen(); } void Aura::HandleModPowerRegenPCT(bool /*apply*/, bool Real) @@ -4378,7 +4436,7 @@ void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real) { if(apply) { - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply); m_target->ModifyHealth(m_modifier.m_amount); } else @@ -4387,7 +4445,7 @@ void Aura::HandleAuraModIncreaseHealth(bool apply, bool Real) m_target->ModifyHealth(-m_modifier.m_amount); else m_target->SetHealth(1); - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(m_modifier.m_amount), apply); } } } @@ -4418,7 +4476,7 @@ void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real) UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType); - m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(m_modifier.m_amount), apply); } void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/) @@ -4429,12 +4487,17 @@ void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/) UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType); - m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_modifier.m_amount), apply); } void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/) { - m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(m_modifier.m_amount), apply); +} + +void Aura::HandleAuraIncreaseBaseHealthPercent(bool apply, bool /*Real*/) +{ + m_target->HandleStatModifier(UNIT_MOD_HEALTH, BASE_PCT, float(m_modifier.m_amount), apply); } /********************************/ @@ -4498,9 +4561,9 @@ void Aura::HandleAuraModCritPercent(bool apply, bool Real) if (GetSpellProto()->EquippedItemClass == -1) { - ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (GetModifierValue()), apply); - ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (GetModifierValue()), apply); - ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (GetModifierValue()), apply); + ((Player*)m_target)->HandleBaseModValue(CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply); + ((Player*)m_target)->HandleBaseModValue(OFFHAND_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply); + ((Player*)m_target)->HandleBaseModValue(RANGED_CRIT_PERCENTAGE, FLAT_MOD, float (m_modifier.m_amount), apply); } else { @@ -4510,13 +4573,28 @@ void Aura::HandleAuraModCritPercent(bool apply, bool Real) void Aura::HandleModHitChance(bool apply, bool Real) { - m_target->m_modMeleeHitChance += apply ? GetModifierValue() : -GetModifierValue(); - m_target->m_modRangedHitChance += apply ? GetModifierValue() : -GetModifierValue(); + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_target)->UpdateMeleeHitChances(); + ((Player*)m_target)->UpdateRangedHitChances(); + } + else + { + m_target->m_modMeleeHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount); + m_target->m_modRangedHitChance += apply ? m_modifier.m_amount : (-m_modifier.m_amount); + } } void Aura::HandleModSpellHitChance(bool apply, bool Real) { - m_target->m_modSpellHitChance += apply ? GetModifierValue(): -GetModifierValue(); + if(m_target->GetTypeId() == TYPEID_PLAYER) + { + ((Player*)m_target)->UpdateSpellHitChances(); + } + else + { + m_target->m_modSpellHitChance += apply ? m_modifier.m_amount: (-m_modifier.m_amount); + } } void Aura::HandleModSpellCritChance(bool apply, bool Real) @@ -4531,7 +4609,7 @@ void Aura::HandleModSpellCritChance(bool apply, bool Real) } else { - m_target->m_baseSpellCritChance += apply ? GetModifierValue():-GetModifierValue(); + m_target->m_baseSpellCritChance += apply ? m_modifier.m_amount:-m_modifier.m_amount; } } @@ -4555,22 +4633,22 @@ void Aura::HandleModSpellCritChanceShool(bool /*apply*/, bool Real) void Aura::HandleModCastingSpeed(bool apply, bool Real) { - m_target->ApplyCastTimePercentMod(GetModifierValue(),apply); + m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply); } void Aura::HandleModMeleeRangedSpeedPct(bool apply, bool Real) { - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK,GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetModifierValue(), apply); + m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply); } void Aura::HandleModCombatSpeedPct(bool apply, bool Real) { - m_target->ApplyCastTimePercentMod(GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK,GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetModifierValue(), apply); + m_target->ApplyCastTimePercentMod(m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(OFF_ATTACK,m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply); } void Aura::HandleModAttackSpeed(bool apply, bool Real) @@ -4578,26 +4656,26 @@ void Aura::HandleModAttackSpeed(bool apply, bool Real) if(!m_target->isAlive() ) return; - m_target->ApplyAttackTimePercentMod(BASE_ATTACK,GetModifierValue(),apply); + m_target->ApplyAttackTimePercentMod(BASE_ATTACK,m_modifier.m_amount,apply); } void Aura::HandleHaste(bool apply, bool Real) { - m_target->ApplyAttackTimePercentMod(BASE_ATTACK, GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(OFF_ATTACK, GetModifierValue(),apply); - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,GetModifierValue(),apply); + m_target->ApplyAttackTimePercentMod(BASE_ATTACK, m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(OFF_ATTACK, m_modifier.m_amount,apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount,apply); } void Aura::HandleAuraModRangedHaste(bool apply, bool Real) { - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, GetModifierValue(), apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK, m_modifier.m_amount, apply); } void Aura::HandleRangedAmmoHaste(bool apply, bool Real) { if(m_target->GetTypeId() != TYPEID_PLAYER) return; - m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,GetModifierValue(), apply); + m_target->ApplyAttackTimePercentMod(RANGED_ATTACK,m_modifier.m_amount, apply); } /********************************/ @@ -4606,7 +4684,7 @@ void Aura::HandleRangedAmmoHaste(bool apply, bool Real) void Aura::HandleAuraModAttackPower(bool apply, bool Real) { - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_VALUE, float(m_modifier.m_amount), apply); } void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real) @@ -4614,13 +4692,13 @@ void Aura::HandleAuraModRangedAttackPower(bool apply, bool Real) if((m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) return; - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply); } void Aura::HandleAuraModAttackPowerPercent(bool apply, bool Real) { //UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1 - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER, TOTAL_PCT, float(m_modifier.m_amount), apply); } void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real) @@ -4629,7 +4707,7 @@ void Aura::HandleAuraModRangedAttackPowerPercent(bool apply, bool Real) return; //UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1 - m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_ATTACK_POWER_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply); } void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real) @@ -4638,18 +4716,20 @@ void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real) if(!Real) return; - if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) - return; + // Recalculate bonus + if(m_target->GetTypeId() == TYPEID_PLAYER && !(m_target->getClassMask() & CLASSMASK_WAND_USERS)) + ((Player*)m_target)->UpdateAttackPowerAndDamage(true); +} - if(m_modifier.m_miscvalue != STAT_INTELLECT) - { - // support required adding UpdateAttackPowerAndDamage calls at stat update - sLog.outError("Aura SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT (212) need support non-intellect stats!"); +void Aura::HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) return; - } // Recalculate bonus - ((Player*)m_target)->UpdateAttackPowerAndDamage(true); + if(m_target->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_target)->UpdateAttackPowerAndDamage(false); } /********************************/ @@ -4679,9 +4759,9 @@ void Aura::HandleModDamageDone(bool apply, bool Real) // apply generic physical damage bonuses including wand case if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER) { - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(GetModifierValue()), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(GetModifierValue()), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_VALUE, float(m_modifier.m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_VALUE, float(m_modifier.m_amount), apply); } else { @@ -4691,9 +4771,9 @@ void Aura::HandleModDamageDone(bool apply, bool Real) if(m_target->GetTypeId() == TYPEID_PLAYER) { if(m_positive) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,GetModifierValue(),apply); + m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS,m_modifier.m_amount,apply); else - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,GetModifierValue(),apply); + m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG,m_modifier.m_amount,apply); } } @@ -4719,7 +4799,7 @@ void Aura::HandleModDamageDone(bool apply, bool Real) for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) { if((m_modifier.m_miscvalue & (1<<i)) != 0) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,GetModifierValue(),apply); + m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i,m_modifier.m_amount,apply); } } else @@ -4727,7 +4807,7 @@ void Aura::HandleModDamageDone(bool apply, bool Real) for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) { if((m_modifier.m_miscvalue & (1<<i)) != 0) - m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,GetModifierValue(),apply); + m_target->ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_NEG+i,m_modifier.m_amount,apply); } } Pet* pet = m_target->GetPet(); @@ -4762,9 +4842,9 @@ void Aura::HandleModDamagePercentDone(bool apply, bool Real) // apply generic physical damage bonuses including wand case if (GetSpellProto()->EquippedItemClass == -1 || m_target->GetTypeId() != TYPEID_PLAYER) { - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(GetModifierValue()), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetModifierValue()), apply); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, float(m_modifier.m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_RANGED, TOTAL_PCT, float(m_modifier.m_amount), apply); } else { @@ -4803,7 +4883,7 @@ void Aura::HandleModOffhandDamagePercent(bool apply, bool Real) sLog.outDebug("AURA MOD OFFHAND DAMAGE"); - m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(GetModifierValue()), apply); + m_target->HandleStatModifier(UNIT_MOD_DAMAGE_OFFHAND, TOTAL_PCT, float(m_modifier.m_amount), apply); } /********************************/ @@ -4816,7 +4896,7 @@ void Aura::HandleModPowerCostPCT(bool apply, bool Real) if(!Real) return; - float amount = GetModifierValue() /100.0f; + float amount = m_modifier.m_amount /100.0f; for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) if(m_modifier.m_miscvalue & (1<<i)) m_target->ApplyModSignedFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+i,amount,apply); @@ -4830,13 +4910,47 @@ void Aura::HandleModPowerCost(bool apply, bool Real) for(int i = 0; i < MAX_SPELL_SCHOOL; ++i) if(m_modifier.m_miscvalue & (1<<i)) - m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,GetModifierValue(),apply); + m_target->ApplyModInt32Value(UNIT_FIELD_POWER_COST_MODIFIER+i,m_modifier.m_amount,apply); +} + +void Aura::HandleNoReagentUseAura(bool Apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + flag96 mask; + Unit::AuraList const& noReagent = m_target->GetAurasByType(SPELL_AURA_NO_REAGENT_USE); + for(Unit::AuraList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i) + mask |= (*i)->m_spellProto->EffectSpellClassMask[(*i)->m_effIndex]; + + m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1 , mask[0]); + m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+1, mask[1]); + m_target->SetUInt32Value(PLAYER_NO_REAGENT_COST_1+2, mask[2]); } /*********************************************************/ /*** OTHERS ***/ /*********************************************************/ +void Aura::HandleAuraAllowOnlyAbility(bool apply, bool Real) +{ + if(!Real) + return; + + if(!apply && m_target->HasAuraType(SPELL_AURA_ALLOW_ONLY_ABILITY)) + return; + + if(m_target->GetTypeId()==TYPEID_PLAYER) + { + if (apply) + m_target->SetFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY); + else + m_target->RemoveFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY); + } +} + void Aura::HandleShapeshiftBoosts(bool apply) { uint32 spellId = 0; @@ -4851,6 +4965,7 @@ void Aura::HandleShapeshiftBoosts(bool apply) break; case FORM_TREE: spellId = 5420; + spellId2 = 34123; break; case FORM_TRAVEL: spellId = 5419; @@ -4884,11 +4999,16 @@ void Aura::HandleShapeshiftBoosts(bool apply) break; case FORM_FLIGHT: spellId = 33948; + spellId2 = 34764; break; case FORM_FLIGHT_EPIC: spellId = 40122; spellId2 = 40121; break; + case FORM_METAMORPHOSIS: + spellId = 54817; + spellId2 = 54879; + break; case FORM_SPIRITOFREDEMPTION: spellId = 27792; spellId2 = 27795; // must be second, this important at aura remove to prevent to early iterator invalidation. @@ -4919,7 +5039,7 @@ void Aura::HandleShapeshiftBoosts(bool apply) if(itr->second->state == PLAYERSPELL_REMOVED) continue; if(itr->first==spellId || itr->first==spellId2) continue; SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); - if (!spellInfo || !(spellInfo->Attributes & ((1<<6) | (1<<7)))) continue; + if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR_PASSIVE | (1<<7)))) continue; if (spellInfo->Stances & (1<<form)) m_target->CastSpell(m_target, itr->first, true, NULL, this); } @@ -4986,9 +5106,9 @@ void Aura::HandleAuraEmpathy(bool apply, bool Real) void Aura::HandleAuraUntrackable(bool apply, bool Real) { if(apply) - m_target->SetFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE); + m_target->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE); else - m_target->RemoveFlag(UNIT_FIELD_BYTES_1, PLAYER_STATE_FLAG_UNTRACKABLE); + m_target->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_UNTRACKABLE); } void Aura::HandleAuraModPacify(bool apply, bool Real) @@ -5051,7 +5171,21 @@ void Aura::HandleModRating(bool apply, bool Real) for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) if (m_modifier.m_miscvalue & (1 << rating)) - ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), GetModifierValue(), apply); + ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), m_modifier.m_amount, apply); +} + +void Aura::HandleModRatingFromStat(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + // Just recalculate ratings + for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) + if (m_modifier.m_miscvalue & (1 << rating)) + ((Player*)m_target)->ApplyRatingMod(CombatRating(rating), 0, apply); } void Aura::HandleForceMoveForward(bool apply, bool Real) @@ -5082,11 +5216,11 @@ void Aura::HandleModTargetResistance(bool apply, bool Real) // show armor penetration if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_NORMAL)) - m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,GetModifierValue(), apply); + m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE,m_modifier.m_amount, apply); // show as spell penetration only full spell penetration bonuses (all resistances except armor and holy if (m_target->GetTypeId() == TYPEID_PLAYER && (m_modifier.m_miscvalue & SPELL_SCHOOL_MASK_SPELL)==SPELL_SCHOOL_MASK_SPELL) - m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,GetModifierValue(), apply); + m_target->ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE,m_modifier.m_amount, apply); } void Aura::HandleShieldBlockValue(bool apply, bool Real) @@ -5096,7 +5230,7 @@ void Aura::HandleShieldBlockValue(bool apply, bool Real) modType = PCT_MOD; if(m_target->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(GetModifierValue()), apply); + ((Player*)m_target)->HandleBaseModValue(SHIELD_BLOCK_VALUE, modType, float(m_modifier.m_amount), apply); } void Aura::HandleAuraRetainComboPoints(bool apply, bool Real) @@ -5114,7 +5248,7 @@ void Aura::HandleAuraRetainComboPoints(bool apply, bool Real) // remove only if aura expire by time (in case combo points amount change aura removed without combo points lost) if( !apply && m_duration==0 && target->GetComboTarget()) if(Unit* unit = ObjectAccessor::GetUnit(*m_target,target->GetComboTarget())) - target->AddComboPoints(unit, -GetModifierValue()); + target->AddComboPoints(unit, -m_modifier.m_amount); } void Aura::HandleModUnattackable( bool Apply, bool Real ) @@ -5144,7 +5278,7 @@ void Aura::HandleSpiritOfRedemption( bool apply, bool Real ) // set stand state (expected in this form) if(!m_target->IsStandState()) - m_target->SetStandState(PLAYER_STATE_NONE); + m_target->SetStandState(UNIT_STAND_STATE_STAND); } m_target->SetHealth(1); @@ -5156,6 +5290,14 @@ void Aura::HandleSpiritOfRedemption( bool apply, bool Real ) void Aura::CleanupTriggeredSpells() { + if (m_spellProto->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellProto->SpellFamilyFlags[1] & 0x00000010 || m_spellProto->SpellFamilyFlags[0] & 0x00000020) + { + // Blood Frenzy remove + m_target->RemoveAurasDueToSpell(30069); + m_target->RemoveAurasDueToSpell(30070); + return; + } + uint32 tSpellId = m_spellProto->EffectTriggerSpell[GetEffIndex()]; if(!tSpellId) return; @@ -5175,14 +5317,6 @@ void Aura::CleanupTriggeredSpells() m_target->RemoveAurasDueToSpell(tSpellId); } -void Aura::HandleAuraPowerBurn(bool apply, bool Real) -{ - if (m_periodicTimer <= 0) - m_periodicTimer += m_modifier.periodictime; - - m_isPeriodic = apply; -} - void Aura::HandleSchoolAbsorb(bool apply, bool Real) { if(!Real) @@ -5205,7 +5339,7 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real) } break; case SPELLFAMILY_MAGE: - if(m_spellProto->SpellFamilyFlags == 0x80100 || m_spellProto->SpellFamilyFlags == 0x8 || m_spellProto->SpellFamilyFlags == 0x100000000LL) + if(m_spellProto->SpellFamilyFlags.IsEqual(0x80100) || m_spellProto->SpellFamilyFlags.IsEqual(0x8) || m_spellProto->SpellFamilyFlags.IsEqual(0,0x1)) { //frost ward, fire ward, ice barrier //+10% from +spd bonus @@ -5214,7 +5348,7 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real) } break; case SPELLFAMILY_WARLOCK: - if(m_spellProto->SpellFamilyFlags == 0x00) + if(m_spellProto->SpellFamilyFlags.IsEqual(0,0,0x40)) { //shadow ward //+10% from +spd bonus @@ -5306,28 +5440,25 @@ void Aura::PeriodicTick() CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); // ignore non positive values (can be result apply spellmods to aura damage - uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; - - uint32 pdamage; + //uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + uint32 pdamage = GetModifier()->m_amount > 0 ? GetModifier()->m_amount : 0; if(m_modifier.m_auraname == SPELL_AURA_PERIODIC_DAMAGE) { - pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),amount,DOT); + pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount()); // Calculate armor mitigation if it is a physical spell // But not for bleed mechanic spells if ( GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL && GetEffectMechanic(GetSpellProto(), m_effIndex) != MECHANIC_BLEED) { - uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage); + uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage, GetSpellProto()); cleanDamage.damage += pdamage - pdamageReductedArmor; pdamage = pdamageReductedArmor; } - //pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); - // Curse of Agony damage-per-tick calculation - if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x0000000000000400LL) && GetSpellProto()->SpellIconID==544) + if (GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags[0] & 0x400) && GetSpellProto()->SpellIconID==544) { // 1..4 ticks, 1/2 from normal tick damage if (m_duration>=((m_maxduration-m_modifier.periodictime)*2/3)) @@ -5339,16 +5470,14 @@ void Aura::PeriodicTick() } } else - pdamage = uint32(m_target->GetMaxHealth()*amount/100); + pdamage = uint32(m_target->GetMaxHealth()*pdamage/100); //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit // Reduce dot damage from resilience for players if (m_target->GetTypeId()==TYPEID_PLAYER) pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - pdamage *= GetStackAmount(); - - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); + pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist, m_spellProto); sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId(),absorb); @@ -5360,6 +5489,7 @@ void Aura::PeriodicTick() data << uint32(1); data << uint32(m_modifier.m_auraname); data << (uint32)pdamage; + data << uint32(0); // overkill data << (uint32)GetSpellSchoolMask(GetSpellProto()); // will be mask in 2.4.x data << (uint32)absorb; data << (uint32)resist; @@ -5380,6 +5510,7 @@ void Aura::PeriodicTick() break; } case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: { Unit *pCaster = GetCaster(); if(!pCaster) @@ -5392,7 +5523,7 @@ void Aura::PeriodicTick() pCaster->SpellHitResult(m_target,GetSpellProto(),false)!=SPELL_MISS_NONE) return; - // Check for immune (not use charges) + // Check for immune if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) return; @@ -5400,80 +5531,24 @@ void Aura::PeriodicTick() uint32 resist=0; CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL ); - uint32 pdamage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; - pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); + //uint32 pdamage = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + uint32 pdamage = GetModifier()->m_amount > 0 ? GetModifier()->m_amount : 0; + pdamage = pCaster->SpellDamageBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount()); //Calculate armor mitigation if it is a physical spell if (GetSpellSchoolMask(GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL) { - uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage); + uint32 pdamageReductedArmor = pCaster->CalcArmorReducedDamage(m_target, pdamage, GetSpellProto()); cleanDamage.damage += pdamage - pdamageReductedArmor; pdamage = pdamageReductedArmor; } - //pdamage = pCaster->SpellDamageBonus(m_target,GetSpellProto(),pdamage,DOT); - - // talent Soul Siphon add bonus to Drain Life spells - if( GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellProto()->SpellFamilyFlags & 0x8) ) - { - // find talent max bonus percentage - Unit::AuraList const& mClassScriptAuras = pCaster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator i = mClassScriptAuras.begin(); i != mClassScriptAuras.end(); ++i) - { - if ((*i)->GetModifier()->m_miscvalue == 4992 || (*i)->GetModifier()->m_miscvalue == 4993) - { - if((*i)->GetEffIndex()!=1) - { - sLog.outError("Expected spell %u structure change, need code update",(*i)->GetId()); - break; - } - - // effect 1 m_amount - int32 maxPercent = (*i)->GetModifier()->m_amount; - // effect 0 m_amount - int32 stepPercent = pCaster->CalculateSpellDamage((*i)->GetSpellProto(),0,(*i)->GetSpellProto()->EffectBasePoints[0],pCaster); - - // count affliction effects and calc additional damage in percentage - int32 modPercent = 0; - Unit::AuraMap const& victimAuras = m_target->GetAuras(); - for (Unit::AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) - { - Aura* aura = itr->second; - if (aura->IsPositive())continue; - SpellEntry const* m_spell = aura->GetSpellProto(); - if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK) - continue; - - SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(m_spell->Id); - SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(m_spell->Id); - - for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) - { - if(_spell_idx->second->skillId == SKILL_AFFLICTION) - { - modPercent += stepPercent; - if (modPercent >= maxPercent) - { - modPercent = maxPercent; - break; - } - } - } - } - pdamage += (pdamage*modPercent/100); - break; - } - } - } - //As of 2.2 resilience reduces damage from DoT ticks as much as the chance to not be critically hit // Reduce dot damage from resilience for players if (m_target->GetTypeId()==TYPEID_PLAYER) pdamage-=((Player*)m_target)->GetDotDamageReduction(pdamage); - pdamage *= GetStackAmount(); - - pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); + pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist, m_spellProto); if(m_target->GetHealth() < pdamage) pdamage = uint32(m_target->GetHealth()); @@ -5487,6 +5562,7 @@ void Aura::PeriodicTick() Unit* target = m_target; // aura can be deleted in DealDamage SpellEntry const* spellProto = GetSpellProto(); float multiplier = spellProto->EffectMultipleValue[GetEffIndex()] > 0 ? spellProto->EffectMultipleValue[GetEffIndex()] : 1; + int32 stackAmount = GetStackAmount(); // Set trigger flag uint32 procAttacker = PROC_FLAG_ON_DO_PERIODIC;// | PROC_FLAG_SUCCESSFUL_HARMFUL_SPELL_HIT; @@ -5510,7 +5586,7 @@ void Aura::PeriodicTick() if(Player *modOwner = pCaster->GetSpellModOwner()) modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_MULTIPLE_VALUE, multiplier); - uint32 heal = pCaster->SpellHealingBonus(spellProto, uint32(new_damage * multiplier), DOT, pCaster); + uint32 heal = pCaster->SpellHealingBonus(pCaster, spellProto, uint32(new_damage * multiplier), DOT, stackAmount); int32 gain = pCaster->ModifyHealth(heal); pCaster->getHostilRefManager().threatAssist(pCaster, gain * 0.5f, spellProto); @@ -5526,22 +5602,17 @@ void Aura::PeriodicTick() return; // heal for caster damage (must be alive) - if(m_target != pCaster && GetSpellProto()->SpellVisual==163 && !pCaster->isAlive()) + if(m_target != pCaster && GetSpellProto()->SpellVisual[0]==163 && !pCaster->isAlive()) return; // ignore non positive values (can be result apply spellmods to aura damage - uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; - - uint32 pdamage; + //uint32 amount = GetModifierValuePerStack() > 0 ? GetModifierValuePerStack() : 0; + uint32 pdamage = GetModifier()->m_amount > 0 ? GetModifier()->m_amount : 0; if(m_modifier.m_auraname==SPELL_AURA_OBS_MOD_HEALTH) - pdamage = uint32(m_target->GetMaxHealth() * amount/100); + pdamage = uint32(m_target->GetMaxHealth() * pdamage * GetStackAmount() / 100); else - pdamage = pCaster->SpellHealingBonus(GetSpellProto(), amount, DOT, m_target); - - pdamage *= GetStackAmount(); - - //pdamage = pCaster->SpellHealingBonus(GetSpellProto(), pdamage, DOT, m_target); + pdamage = pCaster->SpellHealingBonus(m_target, GetSpellProto(), pdamage, DOT, GetStackAmount()); sLog.outDetail("PeriodicTick: %u (TypeId: %u) heal of %u (TypeId: %u) for %u health inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); @@ -5553,6 +5624,7 @@ void Aura::PeriodicTick() data << uint32(1); data << uint32(m_modifier.m_auraname); data << (uint32)pdamage; + data << uint32(0); // wotlk m_target->SendMessageToSet(&data,true); int32 gain = m_target->ModifyHealth(pdamage); @@ -5572,7 +5644,7 @@ void Aura::PeriodicTick() bool haveCastItem = GetCastItemGUID()!=0; // heal for caster damage - if(m_target!=pCaster && spellProto->SpellVisual==163) + if(m_target!=pCaster && spellProto->SpellVisual[0]==163) { uint32 dmg = spellProto->manaPerSecond; if(pCaster->GetHealth() <= dmg && pCaster->GetTypeId()==TYPEID_PLAYER) @@ -5624,12 +5696,12 @@ void Aura::PeriodicTick() return; // ignore non positive values (can be result apply spellmods to aura damage - uint32 pdamage = GetModifierValue() > 0 ? GetModifierValue() : 0; + uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; sLog.outDetail("PeriodicTick: %u (TypeId: %u) power leech of %u (TypeId: %u) for %u dmg inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4) + if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS) break; Powers power = Powers(m_modifier.m_miscvalue); @@ -5686,12 +5758,12 @@ void Aura::PeriodicTick() case SPELL_AURA_PERIODIC_ENERGIZE: { // ignore non positive values (can be result apply spellmods to aura damage - uint32 pdamage = GetModifierValue() > 0 ? GetModifierValue() : 0; + uint32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; sLog.outDetail("PeriodicTick: %u (TypeId: %u) energize %u (TypeId: %u) for %u dmg inflicted by %u", GUID_LOPART(GetCasterGUID()), GuidHigh2TypeId(GUID_HIPART(GetCasterGUID())), m_target->GetGUIDLow(), m_target->GetTypeId(), pdamage, GetId()); - if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue > 4) + if(m_modifier.m_miscvalue < 0 || m_modifier.m_miscvalue >= MAX_POWERS) break; Powers power = Powers(m_modifier.m_miscvalue); @@ -5718,7 +5790,7 @@ void Aura::PeriodicTick() case SPELL_AURA_OBS_MOD_MANA: { // ignore non positive values (can be result apply spellmods to aura damage - uint32 amount = GetModifierValue() > 0 ? GetModifierValue() : 0; + uint32 amount = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; uint32 pdamage = uint32(m_target->GetMaxPower(POWER_MANA) * amount/100); @@ -5754,7 +5826,7 @@ void Aura::PeriodicTick() if(m_target->IsImmunedToDamage(GetSpellSchoolMask(GetSpellProto()))) return; - int32 pdamage = GetModifierValue() > 0 ? GetModifierValue() : 0; + int32 pdamage = m_modifier.m_amount > 0 ? m_modifier.m_amount : 0; Powers powerType = Powers(m_modifier.m_miscvalue); @@ -5788,12 +5860,51 @@ void Aura::PeriodicTick() pCaster->DealSpellDamage(&damageInfo, true); break; } + case SPELL_AURA_MOD_REGEN: + { + int32 gain = m_target->ModifyHealth(m_modifier.m_amount); + if (Unit *caster = GetCaster()) + m_target->getHostilRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellProto()); + break; + } + case SPELL_AURA_MOD_POWER_REGEN: + { + Powers pt = m_target->getPowerType(); + if(int32(pt) != m_modifier.m_miscvalue) + return; + + if ( GetSpellProto()->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED ) + { + // eating anim + m_target->HandleEmoteCommand(EMOTE_ONESHOT_EAT); + } + else if( GetId() == 20577 ) + { + // cannibalize anim + m_target->HandleEmoteCommand(EMOTE_STATE_CANNIBALIZE); + } + + // Warrior talent, gain 1 rage every 3 seconds while in combat + if(pt == POWER_RAGE && m_target->isInCombat()) + m_target->ModifyPower(pt, m_modifier.m_amount*10/17); + break; + } // Here tick dummy auras case SPELL_AURA_PERIODIC_DUMMY: { PeriodicDummyTick(); break; } + case SPELL_AURA_PERIODIC_TRIGGER_SPELL: + { + TriggerSpell(); + break; + } + case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE: + { + TriggerSpellWithValue(); + break; + } default: break; } @@ -5801,114 +5912,77 @@ void Aura::PeriodicTick() void Aura::PeriodicDummyTick() { + Unit *caster = GetCaster(); SpellEntry const* spell = GetSpellProto(); - switch (spell->Id) - { - // Drink - case 430: - case 431: - case 432: - case 1133: - case 1135: - case 1137: - case 10250: - case 22734: - case 27089: - case 34291: - case 43706: - case 46755: + switch (spell->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + switch (spell->Id) { - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus - Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN); - for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i) + // Drink + case 430: + case 431: + case 432: + case 1133: + case 1135: + case 1137: + case 10250: + case 22734: + case 27089: + case 34291: + case 43706: + case 46755: + case 49472: // Drink Coffee + case 61830: { - if ((*i)->GetId() == GetId()) + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + // Search SPELL_AURA_MOD_POWER_REGEN aura for this spell and add bonus + Unit::AuraList const& aura = m_target->GetAurasByType(SPELL_AURA_MOD_POWER_REGEN); + for(Unit::AuraList::const_iterator i = aura.begin(); i != aura.end(); ++i) { - // Get tick number - int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime; - // Default case (not on arenas) - if (tick == 0) + if ((*i)->GetId() == GetId()) { (*i)->GetModifier()->m_amount = m_modifier.m_amount; ((Player*)m_target)->UpdateManaRegen(); // Disable continue m_isPeriodic = false; - } - return; - //********************************************** - // Code commended since arena patch not added - // This feature uses only in arenas - //********************************************** - // Here need increase mana regen per tick (6 second rule) - // on 0 tick - 0 (handled in 2 second) - // on 1 tick - 166% (handled in 4 second) - // on 2 tick - 133% (handled in 6 second) - // Not need update after 3 tick - /* - if (tick > 3) return; - // Apply bonus for 0 - 3 tick - switch (tick) - { - case 0: // 0% - (*i)->GetModifier()->m_amount = m_modifier.m_amount = 0; - break; - case 1: // 166% - (*i)->GetModifier()->m_amount = m_modifier.m_amount * 5 / 3; - break; - case 2: // 133% - (*i)->GetModifier()->m_amount = m_modifier.m_amount * 4 / 3; - break; - default: // 100% - normal regen - (*i)->GetModifier()->m_amount = m_modifier.m_amount; - break; } - ((Player*)m_target)->UpdateManaRegen(); - return;*/ } + return; + } + // Forsaken Skills + case 7054: + { + // Possibly need cast one of them (but + // 7038 Forsaken Skill: Swords + // 7039 Forsaken Skill: Axes + // 7040 Forsaken Skill: Daggers + // 7041 Forsaken Skill: Maces + // 7042 Forsaken Skill: Staves + // 7043 Forsaken Skill: Bows + // 7044 Forsaken Skill: Guns + // 7045 Forsaken Skill: 2H Axes + // 7046 Forsaken Skill: 2H Maces + // 7047 Forsaken Skill: 2H Swords + // 7048 Forsaken Skill: Defense + // 7049 Forsaken Skill: Fire + // 7050 Forsaken Skill: Frost + // 7051 Forsaken Skill: Holy + // 7053 Forsaken Skill: Shadow + return; } - return; - } // // Panda // case 19230: break; -// // Master of Subtlety -// case 31666: break; // // Gossip NPC Periodic - Talk // case 33208: break; // // Gossip NPC Periodic - Despawn // case 33209: break; -// // Force of Nature -// case 33831: break; - // Aspect of the Viper - case 34074: - { - if (m_target->GetTypeId() != TYPEID_PLAYER) - return; - // Should be manauser - if (m_target->getPowerType()!=POWER_MANA) - return; - Unit *caster = GetCaster(); - if (!caster) - return; - // Regen amount is max (100% from spell) on 21% or less mana and min on 92.5% or greater mana (20% from spell) - int mana = m_target->GetPower(POWER_MANA); - int max_mana = m_target->GetMaxPower(POWER_MANA); - int32 base_regen = caster->CalculateSpellDamage(m_spellProto, m_effIndex, m_currentBasePoints, m_target); - float regen_pct = 1.20f - 1.1f * mana / max_mana; - if (regen_pct > 1.0f) regen_pct = 1.0f; - else if (regen_pct < 0.2f) regen_pct = 0.2f; - m_modifier.m_amount = int32 (base_regen * regen_pct); - ((Player*)m_target)->UpdateManaRegen(); - return; - } // // Steal Weapon // case 36207: break; // // Simon Game START timer, (DND) // case 39993: break; -// // Harpooner's Mark -// case 40084: break; // // Knockdown Fel Cannon: break; The Aggro Burst // case 40119: break; // // Old Mount Spell @@ -5921,6 +5995,8 @@ void Aura::PeriodicDummyTick() // case 40846: break; // // Copy Weapon // case 41054: break; +// // Dementia +// case 41404: break; // // Ethereal Ring Visual, Lightning Aura // case 41477: break; // // Ethereal Ring Visual, Lightning Aura (Fork) @@ -5969,6 +6045,8 @@ void Aura::PeriodicDummyTick() // case 43310: break; // // Headless Horseman - Maniacal Laugh, Maniacal, Delayed 17 // case 43884: break; +// // Wretched! +// case 43963: break; // // Headless Horseman - Maniacal Laugh, Maniacal, other, Delayed 17 // case 44000: break; // // Energy Feedback @@ -6035,14 +6113,190 @@ void Aura::PeriodicDummyTick() // case 47407: break; // // Mole Machine Port Schedule // case 47489: break; +// case 47941: break; // Crystal Spike +// case 48200: break; // Healer Aura +// case 48630: break; // Summon Gauntlet Mobs Periodic +// case 49313: break; // Proximity Mine Area Aura // // Mole Machine Portal Schedule // case 49466: break; -// // Drink Coffee -// case 49472: break; +// case 49555: break; // Corpse Explode +// case 49592: break; // Temporal Rift +// case 49957: break; // Cutting Laser +// case 50085: break; // Slow Fall // // Listening to Music // case 50493: break; // // Love Rocket Barrage // case 50530: break; +// Exist more after, need add later + default: + break; + } + break; + case SPELLFAMILY_MAGE: + { + // Mirror Image +// if (spell->Id == 55342) +// return; + break; + } + case SPELLFAMILY_WARRIOR: + { + // Armored to the Teeth + if (spell->SpellIconID == 3516) + { + // Increases your attack power by $s1 for every $s2 armor value you have. + // Calculate AP bonus (from 1 efect of this spell) + int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target); + m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this); + return; + } + break; + } + case SPELLFAMILY_DRUID: + { + switch (spell->Id) + { + // Frenzied Regeneration + case 22842: + { + // Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health. + // Should be manauser + if (m_target->getPowerType()!=POWER_RAGE) + return; + uint32 rage = m_target->GetPower(POWER_RAGE); + // Nothing todo + if (rage == 0) + return; + int32 mod = (rage < 100) ? rage : 100; + int32 points = m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target); + int32 regen = m_target->GetMaxHealth() * (mod * points / 10) / 1000; + m_target->CastCustomSpell(m_target, 22845, ®en, 0, 0, true, 0, this); + m_target->SetPower(POWER_RAGE, rage-mod); + return; + } + // Force of Nature + case 33831: + return; + default: + break; + } + break; + } + case SPELLFAMILY_ROGUE: + { +// switch (spell->Id) +// { + // Master of Subtlety +// case 31666: break; + // Killing Spree +// case 51690: break; + // Overkill +// case 58428: break; +// default: +// break; +// } + break; + } + case SPELLFAMILY_HUNTER: + { + // Explosive Shot + if (spell->SpellFamilyFlags[1] & 0x80000000) + { + if (!caster) + return; + int32 damage = m_modifier.m_amount; + // Full damage to target at 0 tick + if (m_duration > m_modifier.periodictime) + { + caster->CastCustomSpell(m_target, 53352, &damage, 0, 0, true, 0, this); + return; + } + damage/=4; + caster->CastCustomSpell(m_target, 56298, &damage, 0, 0, true, 0, this); + return; + } + switch (spell->Id) + { + // Harpooner's Mark + // case 40084: + // return; + // Feeding Frenzy Rank 1 + case 53511: + if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 ) + m_target->CastSpell(m_target, 60096, true, 0, this); + return; + // Feeding Frenzy Rank 2 + case 53512: + if ( m_target->GetHealth() * 100 < m_target->GetMaxHealth() * 35 ) + m_target->CastSpell(m_target, 60097, true, 0, this); + return; + default: + break; + } + break; + } + case SPELLFAMILY_SHAMAN: + { + // Astral Shift + if (spell->Id == 52179) + { + // Periodic need for remove visual on stun/fear/silence lost + if (!(m_target->GetUInt32Value(UNIT_FIELD_FLAGS)&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED))) + m_target->RemoveAurasDueToSpell(52179); + return; + } + break; + } + case SPELLFAMILY_DEATHKNIGHT: + { + // Death and Decay + if (spell->SpellFamilyFlags[0] & 0x20) + { + if (caster) + caster->CastCustomSpell(m_target, 52212, &m_modifier.m_amount, NULL, NULL, true, 0, this); + return; + } + // Raise Dead +// if (spell->SpellFamilyFlags & 0x0000000000001000LL) +// return; + // Chains of Ice + if (spell->SpellFamilyFlags[1] & 0x00004000) + { + // Get 0 effect aura + Aura *slow = m_target->GetAura(GetId(), 0); + if (slow) + { + slow->ApplyModifier(false, true); + Modifier *mod = slow->GetModifier(); + mod->m_amount+= m_modifier.m_amount; + if (mod->m_amount > 0) mod->m_amount = 0; + slow->ApplyModifier(true, true); + } + return; + } + // Summon Gargoyle +// if (spell->SpellFamilyFlags & 0x0000008000000000LL) +// return; + // Death Rune Mastery +// if (spell->SpellFamilyFlags & 0x0000000000004000LL) +// return; + // Bladed Armor + if (spell->SpellIconID == 2653) + { + // Increases your attack power by $s1 for every $s2 armor value you have. + // Calculate AP bonus (from 1 efect of this spell) + int32 apBonus = m_modifier.m_amount * m_target->GetArmor() / m_target->CalculateSpellDamage(spell, 1, spell->EffectBasePoints[1], m_target); + m_target->CastCustomSpell(m_target, 61217, &apBonus, &apBonus, 0, true, 0, this); + return; + } + // Reaping +// if (spell->SpellIconID == 22) +// return; + // Blood of the North +// if (spell->SpellIconID == 30412) +// return; + break; + } default: break; } @@ -6078,7 +6332,7 @@ void Aura::HandleManaShield(bool apply, bool Real) switch(m_spellProto->SpellFamilyName) { case SPELLFAMILY_MAGE: - if(m_spellProto->SpellFamilyFlags & 0x8000) + if(m_spellProto->SpellFamilyFlags[0] & 0x8000) { // Mana Shield // +50% from +spd bonus @@ -6107,3 +6361,157 @@ void Aura::HandleArenaPreparation(bool apply, bool Real) else m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION); } + +void Aura::HandleAuraControlVehicle(bool apply, bool Real) +{ + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + if(Pet *pet = m_target->GetPet()) + pet->Remove(PET_SAVE_AS_CURRENT); + + WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); + ((Player*)m_target)->GetSession()->SendPacket(&data); +} + +void Aura::HandleAuraConvertRune(bool apply, bool Real) +{ + if(!Real) + return; + + if(m_target->GetTypeId() != TYPEID_PLAYER) + return; + + Player *plr = (Player*)m_target; + + if(plr->getClass() != CLASS_DEATH_KNIGHT) + return; + + // how to determine what rune need to be converted? + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + if(apply) + { + if(!plr->GetRuneCooldown(i)) + { + plr->ConvertRune(i, GetSpellProto()->EffectMiscValueB[m_effIndex]); + break; + } + } + else + { + if(plr->GetCurrentRune(i) == GetSpellProto()->EffectMiscValueB[m_effIndex]) + { + plr->ConvertRune(i, plr->GetBaseRune(i)); + break; + } + } + } +} + +void Aura::HandleModPossess(bool apply, bool Real) +{ + if(!Real) + return; + + Unit* caster = GetCaster(); + if(caster && caster->GetTypeId() == TYPEID_UNIT) + { + HandleModCharm(apply, Real); + return; + } + + if(apply) + { + if(m_target->getLevel() > m_modifier.m_amount) + return; + + m_target->SetCharmedOrPossessedBy(caster, true); + } + else + m_target->RemoveCharmedOrPossessedBy(caster); +} + +void Aura::HandleModPossessPet(bool apply, bool Real) +{ + if(!Real) + return; + + Unit* caster = GetCaster(); + if(!caster || caster->GetTypeId() != TYPEID_PLAYER) + return; + if(caster->GetPet() != m_target) + return; + + if(apply) + m_target->SetCharmedOrPossessedBy(caster, true); + else + { + m_target->RemoveCharmedOrPossessedBy(caster); + + // Reinitialize the pet bar and make the pet come back to the owner + ((Player*)caster)->PetSpellInitialize(); + if(!m_target->getVictim()) + { + m_target->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + m_target->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); + } + } +} + +void Aura::HandleModCharm(bool apply, bool Real) +{ + if(!Real) + return; + + Unit* caster = GetCaster(); + + if(apply) + { + if(int32(m_target->getLevel()) > m_modifier.m_amount) + return; + + m_target->SetCharmedOrPossessedBy(caster, false); + } + else + m_target->RemoveCharmedOrPossessedBy(caster); +} + +void Aura::HandlePhase(bool apply, bool Real) +{ + if(!Real) + return; + + // always non stackable + if(apply) + { + Unit::AuraList const& phases = m_target->GetAurasByType(SPELL_AURA_PHASE); + if(!phases.empty()) + m_target->RemoveAurasDueToSpell(phases.front()->GetId(),this); + } + + // no-phase is also phase state so same code for apply and remove + + // phase auras normally not expected at BG but anyway better check + if(m_target->GetTypeId()==TYPEID_PLAYER) + { + // drop flag at invisible in bg + if(((Player*)m_target)->InBattleGround()) + if(BattleGround *bg = ((Player*)m_target)->GetBattleGround()) + bg->EventPlayerDroppedFlag((Player*)m_target); + + // GM-mode have mask 0xFFFFFFFF + if(!((Player*)m_target)->isGameMaster()) + m_target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL,false); + } + else + m_target->SetPhaseMask(apply ? GetMiscValue() : PHASEMASK_NORMAL,false); + + // need triggering visibility update base at phase update of not GM invisible (other GMs anyway see in any phases) + if(m_target->GetVisibility()!=VISIBILITY_OFF) + m_target->SetVisibility(m_target->GetVisibility()); +} + diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 4912548d5b3..c09feca92b9 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,15 +22,6 @@ #include "SpellAuraDefines.h" -struct DamageManaShield -{ - uint32 m_spellId; - uint32 m_modType; - int32 m_schoolType; - uint32 m_totalAbsorb; - uint32 m_currAbsorb; -}; - struct Modifier { AuraType m_auraname; @@ -100,6 +91,7 @@ class TRINITY_DLL_SPEC Aura void HandleAuraFeatherFall(bool Apply, bool Real); void HandleAuraHover(bool Apply, bool Real); void HandleAddModifier(bool Apply, bool Real); + void HandleAddTargetTrigger(bool Apply, bool Real); void HandleAuraModStun(bool Apply, bool Real); void HandleModDamageDone(bool Apply, bool Real); void HandleAuraUntrackable(bool Apply, bool Real); @@ -111,8 +103,10 @@ class TRINITY_DLL_SPEC Aura void HandleAuraModRegenInterrupt(bool Apply, bool Real); void HandleHaste(bool Apply, bool Real); void HandlePeriodicTriggerSpell(bool Apply, bool Real); + void HandlePeriodicTriggerSpellWithValue(bool apply, bool Real); void HandlePeriodicEnergize(bool Apply, bool Real); void HandleAuraModResistanceExclusive(bool Apply, bool Real); + void HandleAuraModPetTalentsPoints(bool Apply, bool Real); void HandleModStealth(bool Apply, bool Real); void HandleInvisibility(bool Apply, bool Real); void HandleInvisibilityDetect(bool Apply, bool Real); @@ -147,6 +141,7 @@ class TRINITY_DLL_SPEC Aura void HandleModSpellHitChance(bool Apply, bool Real); void HandleAuraModScale(bool Apply, bool Real); void HandlePeriodicManaLeech(bool Apply, bool Real); + void HandlePeriodicHealthFunnel(bool apply, bool Real); void HandleModCastingSpeed(bool Apply, bool Real); void HandleAuraMounted(bool Apply, bool Real); void HandleWaterBreathing(bool Apply, bool Real); @@ -184,10 +179,12 @@ class TRINITY_DLL_SPEC Aura void HandleAuraGhost(bool Apply, bool Real); void HandleAuraAllowFlight(bool Apply, bool Real); void HandleModRating(bool apply, bool Real); + void HandleModRatingFromStat(bool apply, bool Real); void HandleModTargetResistance(bool apply, bool Real); void HandleAuraModAttackPowerPercent(bool apply, bool Real); void HandleAuraModRangedAttackPowerPercent(bool apply, bool Real); void HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real); + void HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real); void HandleSpiritOfRedemption(bool apply, bool Real); void HandleModManaRegen(bool apply, bool Real); void HandleComprehendLanguage(bool apply, bool Real); @@ -197,6 +194,7 @@ class TRINITY_DLL_SPEC Aura void HandleModSpellDamagePercentFromStat(bool apply, bool Real); void HandleModSpellHealingPercentFromStat(bool apply, bool Real); void HandleAuraModDispelResist(bool apply, bool Real); + void HandleAuraControlVehicle(bool apply, bool Real); void HandleModSpellDamagePercentFromAttackPower(bool apply, bool Real); void HandleModSpellHealingPercentFromAttackPower(bool apply, bool Real); void HandleAuraModPacifyAndSilence(bool Apply, bool Real); @@ -209,13 +207,15 @@ class TRINITY_DLL_SPEC Aura void HandlePreventFleeing(bool apply, bool Real); void HandleManaShield(bool apply, bool Real); void HandleArenaPreparation(bool apply, bool Real); + void HandleAuraConvertRune(bool apply, bool Real); + void HandleAuraIncreaseBaseHealthPercent(bool Apply, bool Real); + void HandleNoReagentUseAura(bool Apply, bool Real); + void HandlePhase(bool Apply, bool Real); virtual ~Aura(); void SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue); Modifier* GetModifier() {return &m_modifier;} - int32 GetModifierValuePerStack() {return m_modifier.m_amount;} - int32 GetModifierValue() {return m_modifier.m_amount * m_stackAmount;} int32 GetMiscValue() {return m_spellProto->EffectMiscValue[m_effIndex];} int32 GetMiscBValue() {return m_spellProto->EffectMiscValueB[m_effIndex];} @@ -229,10 +229,15 @@ class TRINITY_DLL_SPEC Aura void SetAuraMaxDuration(int32 duration) { m_maxduration = duration; } int32 GetAuraDuration() const { return m_duration; } void SetAuraDuration(int32 duration) { m_duration = duration; } + void SetAuraDurationAndUpdate(int32 duration) + { + m_duration = duration; + if(GetAuraSlot() < MAX_AURAS) // slot found send data to client + { m_target->UpdateAuraForGroup(GetAuraSlot()); } + } time_t GetAuraApplyTime() { return m_applyTime; } - void UpdateAuraDuration(); - void SendAuraDurationForCaster(Player* caster); - void UpdateSlotCounterAndDuration(); + + SpellModifier *getAuraSpellMod() {return m_spellmod; } uint64 const& GetCasterGUID() const { return m_caster_guid; } Unit* GetCaster() const; @@ -249,14 +254,30 @@ class TRINITY_DLL_SPEC Aura uint8 GetAuraSlot() const { return m_auraSlot; } void SetAuraSlot(uint8 slot) { m_auraSlot = slot; } - void UpdateAuraCharges() + uint8 GetAuraCharges() const { return m_procCharges; } + void SetAuraCharges(uint8 charges) { - uint8 slot = GetAuraSlot(); - - // only aura in slot with charges and without stack limitation - if (slot < MAX_AURAS && m_procCharges >= 1 && GetSpellProto()->StackAmount==0) - SetAuraApplication(slot, m_procCharges - 1); + if (m_procCharges == charges) + return; + m_procCharges = charges; + if(GetAuraSlot() < MAX_AURAS) // slot found send data to client + { m_target->UpdateAuraForGroup(GetAuraSlot()); } } + bool DropAuraCharge() // return true if last charge dropped + { + if (m_procCharges == 0) + return false; + m_procCharges--; + if(GetAuraSlot() < MAX_AURAS) // slot found send data to client + { m_target->UpdateAuraForGroup(GetAuraSlot()); } + return m_procCharges == 0; + } + + int8 GetStackAmount() {return m_stackAmount;} + //int32 GetModifierValuePerStack() {return m_modifier.m_amount / m_stackAmount;} + void SetStackAmount(uint8 num); + bool modStackAmount(int32 num); // return true if last charge dropped + void RefreshAura(); bool IsPositive() { return m_positive; } void SetNegative() { m_positive = false; } @@ -265,7 +286,6 @@ class TRINITY_DLL_SPEC Aura bool IsPermanent() const { return m_permanent; } bool IsAreaAura() const { return m_isAreaAura; } bool IsPeriodic() const { return m_isPeriodic; } - bool IsTrigger() const { return m_isTrigger; } bool IsPassive() const { return m_isPassive; } bool IsPersistent() const { return m_isPersistent; } bool IsDeathPersistent() const { return m_isDeathPersist; } @@ -278,72 +298,67 @@ class TRINITY_DLL_SPEC Aura void _AddAura(); void _RemoveAura(); - void TriggerSpell(); - bool IsUpdated() { return m_updated; } void SetUpdated(bool val) { m_updated = val; } void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; } - int32 m_procCharges; - void SetAuraProcCharges(int32 charges) { m_procCharges = charges; } - Unit* GetTriggerTarget() const; // add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras + void HandleAuraAllowOnlyAbility(bool apply, bool Real); void HandleShapeshiftBoosts(bool apply); // Allow Apply Aura Handler to modify and access m_AuraDRGroup void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } DiminishingGroup getDiminishGroup() const { return m_AuraDRGroup; } + void TriggerSpell(); + void TriggerSpellWithValue(); void PeriodicTick(); void PeriodicDummyTick(); - int32 GetStackAmount() {return m_stackAmount;} - void SetStackAmount(int32 amount) {m_stackAmount=amount;} + bool isAffectedOnSpell(SpellEntry const *spell) const; protected: Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL); Modifier m_modifier; SpellModifier *m_spellmod; - uint32 m_effIndex; + SpellEntry const *m_spellProto; - int32 m_currentBasePoints; // cache SpellEntry::EffectBasePoints and use for set custom base points - uint64 m_caster_guid; Unit* m_target; - int32 m_maxduration; - int32 m_duration; - int32 m_timeCla; + uint64 m_caster_guid; uint64 m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted time_t m_applyTime; - AuraRemoveMode m_removeMode; + int32 m_currentBasePoints; // cache SpellEntry::EffectBasePoints and use for set custom base points + int32 m_maxduration; // Max aura duration + int32 m_duration; // Current time + int32 m_timeCla; // Timer for power per sec calcultion + int32 m_periodicTimer; // Timer for periodic auras - uint8 m_auraSlot; + AuraRemoveMode m_removeMode:8; // Store info for know remove aura reason + DiminishingGroup m_AuraDRGroup:8; // Diminishing + + uint8 m_effIndex; // Aura effect index in spell + uint8 m_auraSlot; // Aura slot on unit (for show in client) + uint8 m_auraFlags; // Aura info flag (for send data to client) + uint8 m_auraLevel; // Aura level (store caster level for correct show level dep amount) + uint8 m_procCharges; // Aura charges (0 for infinite) + uint8 m_stackAmount; // Aura stack amount bool m_positive:1; bool m_permanent:1; bool m_isPeriodic:1; - bool m_isTrigger:1; bool m_isAreaAura:1; bool m_isPassive:1; bool m_isPersistent:1; bool m_isDeathPersist:1; bool m_isRemovedOnShapeLost:1; - bool m_updated:1; + bool m_updated:1; // Prevent remove aura by stack if set bool m_in_use:1; // true while in Aura::ApplyModifier call - int32 m_periodicTimer; - uint32 m_PeriodicEventId; - DiminishingGroup m_AuraDRGroup; - - int32 m_stackAmount; private: void CleanupTriggeredSpells(); - void SetAura(uint32 slot, bool remove) { m_target->SetUInt32Value(UNIT_FIELD_AURA + slot, remove ? 0 : GetId()); } - void SetAuraFlag(uint32 slot, bool add); - void SetAuraLevel(uint32 slot, uint32 level); - void SetAuraApplication(uint32 slot, int8 count); }; class TRINITY_DLL_SPEC AreaAura : public Aura diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 07e5d4afef9..545d03ee76e 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,6 +47,7 @@ #include "Creature.h" #include "Totem.h" #include "CreatureAI.h" +#include "BattleGroundMgr.h" #include "BattleGround.h" #include "BattleGroundEY.h" #include "BattleGroundWS.h" @@ -60,6 +61,7 @@ #include "CellImpl.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" +#include "SkillDiscovery.h" pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= { @@ -104,8 +106,8 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectDispel, // 38 SPELL_EFFECT_DISPEL &Spell::EffectUnused, // 39 SPELL_EFFECT_LANGUAGE &Spell::EffectDualWield, // 40 SPELL_EFFECT_DUAL_WIELD - &Spell::EffectSummonWild, // 41 SPELL_EFFECT_SUMMON_WILD - &Spell::EffectSummonGuardian, // 42 SPELL_EFFECT_SUMMON_GUARDIAN + &Spell::EffectUnused, // 41 SPELL_EFFECT_JUMP + &Spell::EffectUnused, // 42 SPELL_EFFECT_JUMP2 &Spell::EffectTeleUnitsFaceCaster, // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER &Spell::EffectLearnSkill, // 44 SPELL_EFFECT_SKILL_STEP &Spell::EffectAddHonor, // 45 SPELL_EFFECT_ADD_HONOR honor/pvp related @@ -128,16 +130,16 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectPowerBurn, // 62 SPELL_EFFECT_POWER_BURN &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL - &Spell::EffectUnused, // 65 SPELL_EFFECT_HEALTH_FUNNEL unused - &Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused + &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID + &Spell::EffectUnused, // 66 SPELL_EFFECT_CREATE_MANA_GEM (possibly recharge it, misc - is item ID) &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST &Spell::EffectDistract, // 69 SPELL_EFFECT_DISTRACT &Spell::EffectPull, // 70 SPELL_EFFECT_PULL one spell: Distract Move &Spell::EffectPickPocket, // 71 SPELL_EFFECT_PICKPOCKET &Spell::EffectAddFarsight, // 72 SPELL_EFFECT_ADD_FARSIGHT - &Spell::EffectSummonPossessed, // 73 SPELL_EFFECT_SUMMON_POSSESSED - &Spell::EffectSummonTotem, // 74 SPELL_EFFECT_SUMMON_TOTEM + &Spell::EffectUnused, // 73 SPELL_EFFECT_UNTRAIN_TALENTS + &Spell::EffectApplyGlyph, // 74 SPELL_EFFECT_APPLY_GLYPH &Spell::EffectHealMechanical, // 75 SPELL_EFFECT_HEAL_MECHANICAL one spell: Mechanical Patch Kit &Spell::EffectSummonObjectWild, // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD &Spell::EffectScriptEffect, // 77 SPELL_EFFECT_SCRIPT_EFFECT @@ -150,17 +152,17 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectStuck, // 84 SPELL_EFFECT_STUCK &Spell::EffectSummonPlayer, // 85 SPELL_EFFECT_SUMMON_PLAYER &Spell::EffectActivateObject, // 86 SPELL_EFFECT_ACTIVATE_OBJECT - &Spell::EffectSummonTotem, // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1 - &Spell::EffectSummonTotem, // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2 - &Spell::EffectSummonTotem, // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3 - &Spell::EffectSummonTotem, // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4 + &Spell::EffectUnused, // 87 SPELL_EFFECT_WMO_DAMAGE + &Spell::EffectUnused, // 88 SPELL_EFFECT_WMO_REPAIR + &Spell::EffectUnused, // 89 SPELL_EFFECT_WMO_CHANGE + &Spell::EffectUnused, // 90 SPELL_EFFECT_KILL_CREDIT &Spell::EffectUnused, // 91 SPELL_EFFECT_THREAT_ALL one spell: zzOLDBrainwash &Spell::EffectEnchantHeldItem, // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM &Spell::EffectUnused, // 93 SPELL_EFFECT_SUMMON_PHANTASM &Spell::EffectSelfResurrect, // 94 SPELL_EFFECT_SELF_RESURRECT &Spell::EffectSkinning, // 95 SPELL_EFFECT_SKINNING &Spell::EffectUnused, // 96 SPELL_EFFECT_CHARGE - &Spell::EffectSummonCritter, // 97 SPELL_EFFECT_SUMMON_CRITTER + &Spell::EffectUnused, // 97 SPELL_EFFECT_97 &Spell::EffectKnockBack, // 98 SPELL_EFFECT_KNOCK_BACK &Spell::EffectDisEnchant, // 99 SPELL_EFFECT_DISENCHANT &Spell::EffectInebriate, //100 SPELL_EFFECT_INEBRIATE @@ -175,7 +177,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectSummonDeadPet, //109 SPELL_EFFECT_SUMMON_DEAD_PET &Spell::EffectDestroyAllTotems, //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS &Spell::EffectDurabilityDamage, //111 SPELL_EFFECT_DURABILITY_DAMAGE - &Spell::EffectSummonDemon, //112 SPELL_EFFECT_SUMMON_DEMON + &Spell::EffectUnused, //112 SPELL_EFFECT_112 &Spell::EffectResurrectNew, //113 SPELL_EFFECT_RESURRECT_NEW &Spell::EffectTaunt, //114 SPELL_EFFECT_ATTACK_ME &Spell::EffectDurabilityDamagePCT, //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT @@ -195,21 +197,21 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY &Spell::EffectRedirectThreat, //130 SPELL_EFFECT_REDIRECT_THREAT &Spell::EffectUnused, //131 SPELL_EFFECT_131 used in some test spells - &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value + &Spell::EffectNULL, //132 SPELL_EFFECT_PLAY_MUSIC sound id in misc value (SoundEntries.dbc) &Spell::EffectUnlearnSpecialization, //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION unlearn profession specialization &Spell::EffectKillCredit, //134 SPELL_EFFECT_KILL_CREDIT misc value is creature entry &Spell::EffectNULL, //135 SPELL_EFFECT_CALL_PET &Spell::EffectHealPct, //136 SPELL_EFFECT_HEAL_PCT &Spell::EffectEnergisePct, //137 SPELL_EFFECT_ENERGIZE_PCT &Spell::EffectNULL, //138 SPELL_EFFECT_138 Leap - &Spell::EffectUnused, //139 SPELL_EFFECT_139 unused + &Spell::EffectUnused, //139 SPELL_EFFECT_CLEAR_QUEST (misc - is quest ID) &Spell::EffectForceCast, //140 SPELL_EFFECT_FORCE_CAST &Spell::EffectNULL, //141 SPELL_EFFECT_141 damage and reduce speed? &Spell::EffectTriggerSpellWithValue, //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER &Spell::EffectKnockBack, //144 SPELL_EFFECT_KNOCK_BACK_2 Spectral Blast &Spell::EffectNULL, //145 SPELL_EFFECT_145 Black Hole Effect - &Spell::EffectUnused, //146 SPELL_EFFECT_146 unused + &Spell::EffectActivateRune, //146 SPELL_EFFECT_ACTIVATE_RUNE &Spell::EffectQuestFail, //147 SPELL_EFFECT_QUEST_FAIL quest fail &Spell::EffectUnused, //148 SPELL_EFFECT_148 unused &Spell::EffectNULL, //149 SPELL_EFFECT_149 swoop @@ -217,6 +219,12 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectTriggerRitualOfSummoning, //151 SPELL_EFFECT_TRIGGER_SPELL_2 &Spell::EffectNULL, //152 SPELL_EFFECT_152 summon Refer-a-Friend &Spell::EffectNULL, //153 SPELL_EFFECT_CREATE_PET misc value is creature entry + &Spell::EffectNULL, //154 unused + &Spell::EffectTitanGrip, //155 SPELL_EFFECT_TITAN_GRIP Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal. + &Spell::EffectEnchantItemPrismatic, //156 SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC + &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create/learn item/spell for profession + &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling + &Spell::EffectRenamePet //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again }; void Spell::EffectNULL(uint32 /*i*/) @@ -293,7 +301,7 @@ void Spell::EffectEnvirinmentalDMG(uint32 i) // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i]; - m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); + m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist, m_spellInfo); m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false); if(m_caster->GetTypeId() == TYPEID_PLAYER) @@ -347,6 +355,13 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) damage = 200; break; } + // Intercept (warrior spell trigger) + case 20253: + case 61491: + { + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f); + break; + } // arcane charge. must only affect demons (also undead?) case 45072: { @@ -374,7 +389,7 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) case SPELLFAMILY_MAGE: { // Arcane Blast - if(m_spellInfo->SpellFamilyFlags & 0x20000000LL) + if(m_spellInfo->SpellFamilyFlags[0] & 0x20000000) { m_caster->CastSpell(m_caster,36032,true); } @@ -383,29 +398,43 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) case SPELLFAMILY_WARRIOR: { // Bloodthirst - if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL) + if(m_spellInfo->SpellFamilyFlags[1] & 0x400) { damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100); } // Shield Slam - else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x1) damage += int32(m_caster->GetShieldBlockValue()); // Victory Rush - else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x100) { damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false); } + // Revenge ${$m1+$AP*0.207} to ${$M1+$AP*0.207} + else if(m_spellInfo->SpellFamilyFlags[0] & 0x400) + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f); + // Heroic Throw ${$m1+$AP*.50} + else if(m_spellInfo->SpellFamilyFlags[1] & 0x00000001) + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f); + // Shockwave ${$m3/100*$AP} + else if(m_spellInfo->SpellFamilyFlags[1] & 0x00008000) + { + int32 pct = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget); + if (pct > 0) + damage+= int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * pct / 100); + break; + } break; } case SPELLFAMILY_WARLOCK: { // Incinerate Rank 1 & 2 - if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128) + if((m_spellInfo->SpellFamilyFlags[1] & 0x000040) && m_spellInfo->SpellIconID==2128) { // Incinerate does more dmg (dmg*0.25) if the target is Immolated. if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE)) - damage += int32(damage*0.25); + damage += int32(damage*0.25f); } // Conflagrate - consumes immolate @@ -415,75 +444,52 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) Unit::AuraList const &mPeriodic = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i) { - if( (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && ((*i)->GetSpellProto()->SpellFamilyFlags & 4) && + if( (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && ((*i)->GetSpellProto()->SpellFamilyFlags[0] & 4) && (*i)->GetCasterGUID()==m_caster->GetGUID() ) { - unitTarget->RemoveAurasDueToCasterSpell((*i)->GetId(), m_caster->GetGUID()); + unitTarget->RemoveAurasByCasterSpell((*i)->GetId(), m_caster->GetGUID()); break; } } } break; } + case SPELLFAMILY_PRIEST: + { + // Shadow Word: Death - deals damage equal to damage done to caster + if (m_spellInfo->SpellFamilyFlags[1] & 0x2) + m_caster->CastCustomSpell(m_caster, 32409, &damage, 0, 0, true); + break; + } case SPELLFAMILY_DRUID: { // Ferocious Bite - if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual==6587) + if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags[0] & 0x000800000) && m_spellInfo->SpellVisual[0]==6587) { - // converts each extra point of energy into ($f1+$AP/630) additional damage - float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effect_idx]; + // converts each extra point of energy into ($f1+$AP/410) additional damage + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + float multiple = ap / 410 + m_spellInfo->DmgMultiplier[effect_idx]; damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple); + damage += int32(((Player*)m_caster)->GetComboPoints() * ap * 7 / 100); m_caster->SetPower(POWER_ENERGY,0); } // Rake - else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL) + else if(m_spellInfo->SpellFamilyFlags[0] & 0x1000) { damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100); } // Swipe - else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x00100000) { damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f); } - // Starfire - else if ( m_spellInfo->SpellFamilyFlags & 0x0004LL ) - { - Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i) - { - // Starfire Bonus (caster) - switch((*i)->GetModifier()->m_miscvalue) - { - case 5481: // Nordrassil Regalia - bonus - { - Unit::AuraList const& m_periodicDamageAuras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); - for(Unit::AuraList::const_iterator itr = m_periodicDamageAuras.begin(); itr != m_periodicDamageAuras.end(); ++itr) - { - // Moonfire or Insect Swarm (target debuff from any casters) - if ( (*itr)->GetSpellProto()->SpellFamilyFlags & 0x00200002LL ) - { - int32 mod = (*i)->GetModifier()->m_amount; - damage += damage*mod/100; - break; - } - } - break; - } - case 5148: //Improved Starfire - Ivory Idol of the Moongoddes Aura - { - damage += (*i)->GetModifier()->m_amount; - break; - } - } - } - } //Mangle Bonus for the initial damage of Lacerate and Rake - if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) || - (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246)) + if((m_spellInfo->SpellFamilyFlags.IsEqual(0x1000,0,0) && m_spellInfo->SpellIconID==494) || + (m_spellInfo->SpellFamilyFlags.IsEqual(0,0x100,0) && 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 & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID) + if((*i)->GetSpellProto()->SpellFamilyFlags[1] & 0x00000440 && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID) { damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f); break; @@ -494,69 +500,88 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) case SPELLFAMILY_ROGUE: { // Envenom - if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL)) + if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags[1] & 0x8)) { // consume from stack dozes not more that have combo-points if(uint32 combo = ((Player*)m_caster)->GetComboPoints()) { - // count consumed deadly poison doses at target - uint32 doses = 0; - - // remove consumed poison doses + Aura *poison = 0; + // Lookup for Deadly poison (only attacker applied) Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); - for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;) - { - // Deadly poison (only attacker applied) - if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) && - (*itr)->GetSpellProto()->SpellVisual==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() ) + for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) + if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && + (*itr)->GetSpellProto()->SpellFamilyFlags[0] & 0x10000 && + (*itr)->GetCasterGUID()==m_caster->GetGUID() ) { - --combo; - ++doses; - - unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex()); - - itr = auras.begin(); + poison = *itr; + break; } - else - ++itr; + // count consumed deadly poison doses at target + if (poison) + { + uint32 spellId = poison->GetId(); + uint32 doses = poison->GetStackAmount(); + if (doses > combo) + doses = combo; + for (int i=0; i< doses; i++) + unitTarget->RemoveSingleSpellAurasFromStack(spellId); + damage *= doses; + damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses); } - - damage *= doses; - damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses); - // Eviscerate and Envenom Bonus Damage (item set effect) if(m_caster->GetDummyAura(37169)) damage += ((Player*)m_caster)->GetComboPoints()*40; } } // Eviscerate - else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER) + else if((m_spellInfo->SpellFamilyFlags[0] & 0x00020000) && m_caster->GetTypeId()==TYPEID_PLAYER) { if(uint32 combo = ((Player*)m_caster)->GetComboPoints()) { - damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * combo * 0.03f); + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + damage += irand(int32(ap * combo * 0.03f), int32(ap * combo * 0.07f)); // Eviscerate and Envenom Bonus Damage (item set effect) if(m_caster->GetDummyAura(37169)) damage += combo*40; } } + // Gouge + else if(m_spellInfo->SpellFamilyFlags[0] & 0x8) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f); + } + // Instant Poison + else if(m_spellInfo->SpellFamilyFlags[0] & 0x2000) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f); + } + // Wound Poison + else if(m_spellInfo->SpellFamilyFlags[0] & 0x10000000) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f); + } break; } case SPELLFAMILY_HUNTER: { // Mongoose Bite - if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual==342) + if((m_spellInfo->SpellFamilyFlags[0] & 0x2) && m_spellInfo->SpellVisual[0]==342) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); + } + // Counterattack + else if(m_spellInfo->SpellFamilyFlags[1] & 0x00080000) { - damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2); + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); } // Arcane Shot - else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0) + else if((m_spellInfo->SpellFamilyFlags[0] & 0x00000800) && m_spellInfo->maxLevel > 0) { - damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15); + damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15f); } // Steady Shot - else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x1) { int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE)); damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f); @@ -578,28 +603,58 @@ void Spell::SpellDamageSchoolDmg(uint32 effect_idx) if(found) damage += m_spellInfo->EffectBasePoints[1]; } - //Explosive Trap Effect - else if(m_spellInfo->SpellFamilyFlags & 0x00000004) + // Explosive Trap Effect + else if(m_spellInfo->SpellFamilyFlags[0] & 0x00000004) { - damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1); + damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1f); } break; } case SPELLFAMILY_PALADIN: { - //Judgement of Vengeance - if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292) + // Judgement of Vengeance ${1+0.22*$SPH+0.14*$AP} + 10% for each application of Holy Vengeance on the target + if((m_spellInfo->SpellFamilyFlags[1] & 0x8) && m_spellInfo->SpellIconID==2292) { + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) + + m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); + damage+=int32(ap * 0.14f) + int32(holy * 22 / 100); + // Get stack of Holy Vengeance on the target added by caster uint32 stacks = 0; Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE); for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr) if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID()) - ++stacks; - if(!stacks) - //No damage if the target isn't affected by this - damage = -1; - else - damage *= stacks; + { + stacks = (*itr)->GetStackAmount(); + break; + } + // + 10% for each application of Holy Vengeance on the target + if(stacks) + damage += damage * stacks * 10 /100; + } + // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) - ranged sdb for future + else if(m_spellInfo->SpellFamilyFlags[0] & 0x4000) + { + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) + + m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); + damage += int32(ap * 0.07f) + int32(holy * 7 / 100); + } + // Hammer of Wrath ($m1+0.15*$SPH+0.15*$AP) - ranged type sdb future fix + else if(m_spellInfo->SpellFamilyFlags[1] & 0x00000080) + { + float ap = m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)) + + m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget); + damage += int32(ap * 0.15f) + int32(holy * 15 / 100); + } + // Hammer of the Righteous + else if(m_spellInfo->SpellFamilyFlags[1]&0x00040000) + { + // Add main hand dps * effect[2] amount + float averange = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2; + int32 count = m_caster->CalculateSpellDamage(m_spellInfo, 2, m_spellInfo->EffectBasePoints[2], unitTarget); + damage += count * int32(averange * 1000) / m_caster->GetAttackTime(BASE_ATTACK); } break; } @@ -637,7 +692,7 @@ void Spell::EffectDummy(uint32 i) if (!creatureTarget || !pGameObj) return; - if (!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 181574, creatureTarget->GetMap(), + if (!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 181574, creatureTarget->GetMap(), creatureTarget->GetPhaseMask(), creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1)) { @@ -745,12 +800,6 @@ void Spell::EffectDummy(uint32 i) m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL); return; } - case 12975: //Last Stand - { - int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3); - m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL); - return; - } case 13120: // net-o-matic { if(!unitTarget) @@ -787,30 +836,6 @@ void Spell::EffectDummy(uint32 i) } return; } - case 14185: // Preparation Rogue - { - if(m_caster->GetTypeId()!=TYPEID_PLAYER) - return; - - //immediately finishes the cooldown on certain Rogue abilities - const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) - { - uint32 classspell = itr->first; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); - - if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL)) - { - ((Player*)m_caster)->RemoveSpellCooldown(classspell); - - WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); - data << uint32(classspell); - data << uint64(m_caster->GetGUID()); - ((Player*)m_caster)->GetSession()->SendPacket(&data); - } - } - return; - } case 15998: // Capture Worg Pup case 29435: // Capture Female Kaliri Hatchling { @@ -875,19 +900,20 @@ void Spell::EffectDummy(uint32 i) if(creatureTarget->isPet()) return; + GameObject* Crystal_Prison = m_caster->SummonGameObject(179644, creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, creatureTarget->GetRespawnTime()-time(NULL)); + sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019\n"); + creatureTarget->setDeathState(JUST_DIED); creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view - GameObject* Crystal_Prison = m_caster->SummonGameObject(179644, creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, creatureTarget->GetRespawnTime()-time(NULL)); - sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019\n"); WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8); data << uint64(Crystal_Prison->GetGUID()); m_caster->SendMessageToSet(&data,true); return; } - case 23074: // Arc. Dragonling + case 23074: // Arcanite Dragonling if (!m_CastItem) return; m_caster->CastSpell(m_caster,19804,true,m_CastItem); return; @@ -1205,6 +1231,12 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(m_caster, 30452, true, NULL); return; } + case 53341: + case 53343: + { + m_caster->CastSpell(m_caster,54586,true); + return; + } } //All IconID Check in there @@ -1278,65 +1310,119 @@ void Spell::EffectDummy(uint32 i) break; case SPELLFAMILY_WARRIOR: // Charge - if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual == 867) + if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual[0] == 867) { int32 chargeBasePoints0 = damage; m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true); return; } + //Slam + if(m_spellInfo->SpellFamilyFlags[0] & 0x200000 && m_spellInfo->SpellIconID == 559) + { + int32 bp0 = damage; + m_caster->CastCustomSpell(unitTarget, 50783, &bp0, NULL, NULL, true, 0); + } // Execute - if(m_spellInfo->SpellFamilyFlags & 0x20000000) + if(m_spellInfo->SpellFamilyFlags[0] & 0x20000000) { if(!unitTarget) return; + uint32 rage = m_caster->GetPower(POWER_RAGE); + // Glyph of Execution bonus + if (Aura *aura = m_caster->GetDummyAura(58367)) + rage+=aura->GetModifier()->m_amount; + spell_id = 20647; - bp = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]); + bp = damage+int32(rage * m_spellInfo->DmgMultiplier[i] + + m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); m_caster->SetPower(POWER_RAGE,0); break; } - if(m_spellInfo->Id==21977) //Warrior's Wrath + // Slam + if(m_spellInfo->SpellFamilyFlags[0] & 0x200000) { if(!unitTarget) return; - - m_caster->CastSpell(unitTarget,21887,true); // spell mod + m_damage+=m_caster->CalculateDamage(m_attackType, false); + m_damage+=damage; return; } + switch(m_spellInfo->Id) + { + // Warrior's Wrath + case 21977: + { + if(!unitTarget) + return; + m_caster->CastSpell(unitTarget,21887,true); // spell mod + return; + } + // Last Stand + case 12975: + { + int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3); + m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL); + return; + } + // Bloodthirst + case 23881: + { + m_caster->CastCustomSpell(unitTarget, 23885, &damage, NULL, NULL, true, NULL); + return; + } + } break; case SPELLFAMILY_WARLOCK: - //Life Tap (only it have this with dummy effect) - if (m_spellInfo->SpellFamilyFlags == 0x40000) + // Life Tap + if (m_spellInfo->SpellFamilyFlags[0] & 0x40000) { - float cost = damage; - - if(Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost,this); - - int32 dmg = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(cost > 0 ? cost : 0), SPELL_DIRECT_DAMAGE); - - if(int32(m_caster->GetHealth()) > dmg) + // In 303 exist spirit depend + uint32 spirit = m_caster->GetStat(STAT_SPIRIT); + switch (m_spellInfo->Id) + { + case 1454: damage+=spirit; break; + case 1455: damage+=spirit*15/10; break; + case 1456: damage+=spirit*2; break; + case 11687: damage+=spirit*25/10; break; + case 11688: + case 11689: + case 27222: + case 57946: damage+=spirit*3; break; + default: + sLog.outError("Spell::EffectDummy: %u Life Tap need set spirit multipler", m_spellInfo->Id); + return; + } +// Think its not need (also need remove Life Tap from SpellDamageBonus or add new value) +// damage = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(damage > 0 ? damage : 0), SPELL_DIRECT_DAMAGE); + if(int32(unitTarget->GetHealth()) > damage) { // Shouldn't Appear in Combat Log - m_caster->ModifyHealth(-dmg); - - int32 mana = dmg; + unitTarget->ModifyHealth(-damage); + int32 mana = damage; + // Improved Life Tap mod Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr) { - // only Imp. Life Tap have this in combination with dummy aura if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208) mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100; } - - m_caster->CastCustomSpell(m_caster,31818,&mana,NULL,NULL,true,NULL); + m_caster->CastCustomSpell(unitTarget, 31818, &mana, NULL, NULL, true); // Mana Feed - int32 manaFeedVal = m_caster->CalculateSpellDamage(m_spellInfo,1, m_spellInfo->EffectBasePoints[1],m_caster); - manaFeedVal = manaFeedVal * mana / 100; + int32 manaFeedVal = 0; + Unit::AuraList const& mod = m_caster->GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER); + for(Unit::AuraList::const_iterator itr = mod.begin(); itr != mod.end(); ++itr) + { + if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 1982) + manaFeedVal+= (*itr)->GetModifier()->m_amount; + } if(manaFeedVal > 0) - m_caster->CastCustomSpell(m_caster,32553,&manaFeedVal,NULL,NULL,true,NULL); + { + manaFeedVal = manaFeedVal * mana / 100; + m_caster->CastCustomSpell(m_caster, 32553, &manaFeedVal, NULL, NULL, true, NULL); + } } else SendCastResult(SPELL_FAILED_FIZZLE); @@ -1344,6 +1430,30 @@ void Spell::EffectDummy(uint32 i) } break; case SPELLFAMILY_PRIEST: + // Penance + if (m_spellInfo->SpellFamilyFlags[1] & 0x00800000) + { + if (!unitTarget) + return; + + int hurt = 0; + int heal = 0; + switch(m_spellInfo->Id) + { + case 47540: hurt = 47758; heal = 47757; break; + case 53005: hurt = 53001; heal = 52986; break; + case 53006: hurt = 53002; heal = 52987; break; + case 53007: hurt = 53003; heal = 52988; break; + default: + sLog.outError("Spell::EffectDummy: Spell %u Penance need set correct heal/damage spell", m_spellInfo->Id); + return; + } + if (m_caster->IsFriendlyTo(unitTarget)) + m_caster->CastSpell(unitTarget, heal, true, 0); + else + m_caster->CastSpell(unitTarget, hurt, true, 0); + return; + } switch(m_spellInfo->Id ) { case 28598: // Touch of Weakness triggered spell @@ -1371,25 +1481,10 @@ void Spell::EffectDummy(uint32 i) } break; case SPELLFAMILY_DRUID: - switch(m_spellInfo->Id ) - { - case 5420: // Tree of Life passive - { - // Tree of Life area effect - int32 health_mod = int32(m_caster->GetStat(STAT_SPIRIT)/4); - m_caster->CastCustomSpell(m_caster,34123,&health_mod,NULL,NULL,true,NULL); - return; - } - } break; case SPELLFAMILY_ROGUE: switch(m_spellInfo->Id ) { - case 31231: // Cheat Death - { - m_caster->CastSpell(m_caster,45182,true); - return; - } case 5938: // Shiv { if(m_caster->GetTypeId() != TYPEID_PLAYER) @@ -1425,36 +1520,38 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(unitTarget, 5940, true); return; } - } - break; - case SPELLFAMILY_HUNTER: - // Kill command - if(m_spellInfo->SpellFamilyFlags & 0x00080000000000LL) - { - if(m_caster->getClass()!=CLASS_HUNTER) - return; + case 14185: // Preparation Rogue + { + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; - // clear hunter crit aura state - m_caster->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE,false); + //immediately finishes the cooldown on certain Rogue abilities + const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap(); + for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) + { + uint32 classspell = itr->first; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell); - // additional damage from pet to pet target - Pet* pet = m_caster->GetPet(); - if(!pet || !pet->getVictim()) - return; + if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags[1] & 0x00000240 || spellInfo->SpellFamilyFlags[0] & 0x00000860)) + { + ((Player*)m_caster)->RemoveSpellCooldown(classspell); - uint32 spell_id = 0; - switch (m_spellInfo->Id) + WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8)); + data << uint32(classspell); + data << uint64(m_caster->GetGUID()); + ((Player*)m_caster)->GetSession()->SendPacket(&data); + } + } + return; + } + case 31231: // Cheat Death { - case 34026: spell_id = 34027; break; // rank 1 - default: - sLog.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo->Id); + m_caster->CastSpell(m_caster,45182,true); return; } - - pet->CastSpell(pet->getVictim(), spell_id, true); - return; } - + break; + case SPELLFAMILY_HUNTER: switch(m_spellInfo->Id) { case 23989: //Readiness talent @@ -1512,6 +1609,8 @@ void Spell::EffectDummy(uint32 i) case 20930: hurt = 25902; heal = 25903; break; case 27174: hurt = 27176; heal = 27175; break; case 33072: hurt = 33073; heal = 33074; break; + case 48824: hurt = 48822; heal = 48820; break; + case 48825: hurt = 48823; heal = 48821; break; default: sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id); return; @@ -1542,10 +1641,7 @@ void Spell::EffectDummy(uint32 i) mod->value = -50; mod->type = SPELLMOD_PCT; mod->spellId = m_spellInfo->Id; - mod->effectId = i; - mod->lastAffected = NULL; - mod->mask = 0x0000020000000000LL; - mod->charges = 0; + mod->mask[1] = 0x00000200; ((Player*)m_caster)->AddSpellMod(mod, true); m_caster->CastSpell(unitTarget,spell_proto,true,NULL); @@ -1561,6 +1657,14 @@ void Spell::EffectDummy(uint32 i) switch(m_spellInfo->Id) { + // Judgement of Righteousness (0.2*$AP+0.32*$SPH) holy added in spellDamagBonus + case 20187: + { + if (!unitTarget) + return; + m_damage+=int32(0.2f*m_caster->GetTotalAttackPowerValue(BASE_ATTACK)); + return; + } case 31789: // Righteous Defense (step 1) { // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target) @@ -1627,8 +1731,10 @@ void Spell::EffectDummy(uint32 i) break; case SPELLFAMILY_SHAMAN: //Shaman Rockbiter Weapon - if (m_spellInfo->SpellFamilyFlags == 0x400000) + if (m_spellInfo->SpellFamilyFlags.IsEqual(0x400000)) { + // TODO: use expect spell for enchant (if exist talent) + // In 3.0.3 no mods present for rockbiter uint32 spell_id = 0; switch(m_spellInfo->Id) { @@ -1636,11 +1742,6 @@ void Spell::EffectDummy(uint32 i) case 8018: spell_id = 36750; break; // Rank 2 case 8019: spell_id = 36755; break; // Rank 3 case 10399: spell_id = 36759; break; // Rank 4 - case 16314: spell_id = 36763; break; // Rank 5 - case 16315: spell_id = 36766; break; // Rank 6 - case 16316: spell_id = 36771; break; // Rank 7 - case 25479: spell_id = 36775; break; // Rank 8 - case 25485: spell_id = 36499; break; // Rank 9 default: sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id); return; @@ -1678,18 +1779,57 @@ void Spell::EffectDummy(uint32 i) } return; } - - if(m_spellInfo->Id == 39610) // Mana-Tide Totem effect + // Healing Stream Totem + if(m_spellInfo->SpellFamilyFlags[0] & 0x2000) + { + m_caster->CastCustomSpell(unitTarget, 52042, &damage, 0, 0, true, 0, 0, m_originalCasterGUID); + return; + } + // Mana Spring Totem + if(m_spellInfo->SpellFamilyFlags[0] & 0x4000) + { + if(unitTarget->getPowerType()!=POWER_MANA) + return; + m_caster->CastCustomSpell(unitTarget, 52032, &damage, 0, 0, true, 0, 0, m_originalCasterGUID); + return; + } + if(m_spellInfo->Id == 39610) // Mana Tide Totem effect { if(!unitTarget || unitTarget->getPowerType() != POWER_MANA) return; - + // Glyph of Mana Tide + Unit *owner = m_caster->GetOwner(); + if (owner) + if (Aura *dummy = owner->GetDummyAura(55441)) + damage+=dummy->GetModifier()->m_amount; // Regenerate 6% of Total Mana Every 3 secs int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA) * damage / 100; m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID); return; } - + // Lava Lash + if (m_spellInfo->SpellFamilyFlags[2] & 0x00000004) + { + if (m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + Item *item = ((Player*)m_caster)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + if (item) + { + // Damage is increased if your off-hand weapon is enchanted with Flametongue. + Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr) + { + if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_SHAMAN && + (*itr)->GetSpellProto()->SpellFamilyFlags[0] & 0x200000 && + (*itr)->GetCastItemGUID() == item->GetGUID()) + { + m_damage += m_damage * damage / 100; + return; + } + } + } + return; + } break; } @@ -1703,7 +1843,7 @@ void Spell::EffectDummy(uint32 i) sLog.outError("EffectDummy of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, spell_id); return; } - + Spell* spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID, NULL, true); if(bp) spell->m_currentBasePoints[0] = bp; SpellCastTargets targets; @@ -1809,7 +1949,7 @@ void Spell::EffectTriggerSpell(uint32 i) if (!spellInfo) continue; - if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH) + if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_STEALTH) { spellId = spellInfo->Id; break; @@ -1966,12 +2106,7 @@ void Spell::EffectTriggerMissileSpell(uint32 effect_idx) if (m_CastItem) DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id); - Spell *spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID ); - - SpellCastTargets targets; - targets.setDestination(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ); - spell->m_CastItem = m_CastItem; - spell->prepare(&targets, NULL); + m_caster->CastSpell(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, spellInfo->Id, true, m_CastItem, 0, m_originalCasterGUID); } void Spell::EffectTeleportUnits(uint32 i) @@ -2106,17 +2241,12 @@ void Spell::EffectApplyAura(uint32 i) if(!unitTarget) return; - SpellImmuneList const& list = unitTarget->m_spellImmune[IMMUNITY_STATE]; - for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr) - if(itr->type == m_spellInfo->EffectApplyAuraName[i]) - return; - // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 && (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) return; - Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster; + Unit* caster = m_originalCaster ? m_originalCaster : m_caster; if(!caster) return; @@ -2129,6 +2259,13 @@ void Spell::EffectApplyAura(uint32 i) unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,caster,m_diminishLevel); Aur->setDiminishGroup(m_diminishGroup); + //apply mods only here, area auras don't have duration + duration = caster->ModSpellDuration(m_spellInfo, i, unitTarget, duration); + + //mod duration of channeled aura by spell haste + if (IsChanneledSpell(m_spellInfo)) + m_caster->ModSpellCastTime(m_spellInfo, duration); + // if Aura removed and deleted, do not continue. if(duration== 0 && !(Aur->IsPermanent())) { @@ -2153,33 +2290,8 @@ void Spell::EffectApplyAura(uint32 i) if(!Aur) return; - // TODO Make a way so it works for every related spell! - if(unitTarget->GetTypeId()==TYPEID_PLAYER) // Negative buff should only be applied on players - { - uint32 spellId = 0; - if(m_spellInfo->CasterAuraStateNot==AURA_STATE_WEAKENED_SOUL || m_spellInfo->TargetAuraStateNot==AURA_STATE_WEAKENED_SOUL) - spellId = 6788; // Weakened Soul - else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_FORBEARANCE || m_spellInfo->TargetAuraStateNot==AURA_STATE_FORBEARANCE) - spellId = 25771; // Forbearance - else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_HYPOTHERMIA) - spellId = 41425; // Hypothermia - else if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages - spellId = 11196; // Recently Bandaged - else if( (m_spellInfo->AttributesEx & 0x20) && (m_spellInfo->AttributesEx2 & 0x20000) ) - spellId = 23230; // Blood Fury - Healing Reduction - - SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(spellId); - if (AdditionalSpellInfo) - { - // applied at target by target - Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, NULL, unitTarget,unitTarget, 0); - unitTarget->AddAura(AdditionalAura); - sLog.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo->EffectApplyAuraName[0]); - } - } - // Prayer of Mending (jump animation), we need formal caster instead original for correct animation - if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL)) + if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags[1] & 0x000020)) m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID); } @@ -2230,7 +2342,8 @@ void Spell::EffectPowerDrain(uint32 i) unitTarget->ModifyPower(drain_power,-new_damage); - if(drain_power == POWER_MANA) + // Don`t restore from self drain + if(drain_power == POWER_MANA && m_caster != unitTarget) { float manaMultiplier = m_spellInfo->EffectMultipleValue[i]; if(manaMultiplier==0) @@ -2371,7 +2484,7 @@ void Spell::SpellDamageHeal(uint32 /*i*/) Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) if((*i)->GetId() == 45062) - damageAmount+=(*i)->GetModifierValue(); + damageAmount+=(*i)->GetModifier()->m_amount; if (damageAmount) m_caster->RemoveAurasDueToSpell(45062); @@ -2386,7 +2499,7 @@ void Spell::SpellDamageHeal(uint32 /*i*/) for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i) { if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID - && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) ) + && ((*i)->GetSpellProto()->SpellFamilyFlags.IsEqual(0x40) || (*i)->GetSpellProto()->SpellFamilyFlags.IsEqual(0x10)) ) { if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration()) targetAura = *i; @@ -2406,21 +2519,21 @@ void Spell::SpellDamageHeal(uint32 /*i*/) idx++; } - int32 tickheal = targetAura->GetModifierValuePerStack(); + int32 tickheal = targetAura->GetModifier()->m_amount; if(Unit* auraCaster = targetAura->GetCaster()) - tickheal = auraCaster->SpellHealingBonus(targetAura->GetSpellProto(), tickheal, DOT, unitTarget); + tickheal = auraCaster->SpellHealingBonus(unitTarget, targetAura->GetSpellProto(), tickheal, DOT); //int32 tickheal = targetAura->GetSpellProto()->EffectBasePoints[idx] + 1; //It is said that talent bonus should not be included - //int32 tickheal = targetAura->GetModifierValue(); + int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx]; addhealth += tickheal * tickcount; - unitTarget->RemoveAurasDueToCasterSpell(targetAura->GetId(), targetAura->GetCasterGUID()); + unitTarget->RemoveAurasByCasterSpell(targetAura->GetId(), targetAura->GetCasterGUID()); //addhealth += tickheal * tickcount; //addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget); } else - addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget); + addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, addhealth, HEAL); m_damage -= addhealth; } @@ -2461,7 +2574,7 @@ void Spell::EffectHealMechanical( uint32 /*i*/ ) if (!caster) return; - uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget); + uint32 addhealth = caster->SpellHealingBonus(unitTarget, m_spellInfo, uint32(damage), HEAL); caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false); unitTarget->ModifyHealth( int32(damage) ); } @@ -2492,7 +2605,7 @@ void Spell::EffectHealthLeech(uint32 i) if(m_caster->isAlive()) { - new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster); + new_damage = m_caster->SpellHealingBonus(m_caster, m_spellInfo, new_damage, HEAL); m_caster->ModifyHealth(new_damage); @@ -2545,8 +2658,8 @@ void Spell::DoCreateItem(uint32 i, uint32 itemtype) if (num_to_add < 1) num_to_add = 1; - if (num_to_add > pProto->Stackable) - num_to_add = pProto->Stackable; + if (num_to_add > pProto->GetMaxStackSize()) + num_to_add = pProto->GetMaxStackSize(); // init items_count to 1, since 1 item will be created regardless of specialization int items_count=1; @@ -2638,6 +2751,21 @@ void Spell::EffectCreateItem(uint32 i) DoCreateItem(i,m_spellInfo->EffectItemType[i]); } +void Spell::EffectCreateItem2(uint32 i) +{ + // special case: generate using spell_loot_template + if(!m_spellInfo->EffectItemType[i]) + { + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + + // create some random items + ((Player*)m_caster)->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell); + return; + } + DoCreateItem(i,m_spellInfo->EffectItemType[i]); +} + void Spell::EffectPersistentAA(uint32 i) { float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); @@ -2668,6 +2796,8 @@ void Spell::EffectEnergize(uint32 i) if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) return; + Powers power = Powers(m_spellInfo->EffectMiscValue[i]); + // Some level depends spells int multiplier = 0; int level_diff = 0; @@ -2698,8 +2828,6 @@ void Spell::EffectEnergize(uint32 i) if(damage < 0) return; - Powers power = Powers(m_spellInfo->EffectMiscValue[i]); - if(unitTarget->GetMaxPower(power) == 0) return; @@ -2767,7 +2895,7 @@ void Spell::EffectEnergisePct(uint32 i) uint32 gain = damage * maxPower / 100; unitTarget->ModifyPower(power, gain); - m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power); + m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, gain, power); } void Spell::SendLoot(uint64 guid, LootType loottype) @@ -2930,10 +3058,10 @@ void Spell::EffectOpenLock(uint32 /*i*/) } // check key - for(int i = 0; i < 5; ++i) + for(int i = 0; i < 8; ++i) { - // type==1 This means lockInfo->key[i] is an item - if(lockInfo->keytype[i]==LOCK_KEY_ITEM && lockInfo->key[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[i]) + // Type==1 This means lockInfo->Index[i] is an item + if(lockInfo->Type[i]==LOCK_KEY_ITEM && lockInfo->Index[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->Index[i]) { SendLoot(guid, loottype); return; @@ -2951,9 +3079,9 @@ void Spell::EffectOpenLock(uint32 /*i*/) // skill bonus provided by casting spell (mostly item spells) uint32 spellSkillBonus = uint32(damage/*m_currentBasePoints[0]+1*/); - uint32 reqSkillValue = lockInfo->requiredminingskill; + uint32 reqSkillValue = lockInfo->Skill[0]; - if(lockInfo->requiredlockskill) // required pick lock skill applying + if(lockInfo->Skill[1]) // required pick lock skill applying { if(SkillId != SKILL_LOCKPICKING) // wrong skill (cheating?) { @@ -2961,7 +3089,7 @@ void Spell::EffectOpenLock(uint32 /*i*/) return; } - reqSkillValue = lockInfo->requiredlockskill; + reqSkillValue = lockInfo->Skill[1]; } else if(SkillId == SKILL_LOCKPICKING) // apply picklock skill to wrong target { @@ -3144,6 +3272,9 @@ void Spell::EffectSummonType(uint32 i) case SUMMON_TYPE_POSESSED2: case SUMMON_TYPE_POSESSED3: EffectSummonPossessed(i); + case SUMMON_TYPE_FORCE_OF_NATURE: + case SUMMON_TYPE_GUARDIAN2: + EffectSummonGuardian(i); break; case SUMMON_TYPE_WILD: EffectSummonWild(i); @@ -3191,7 +3322,7 @@ void Spell::EffectSummon(uint32 i) Pet* spawnCreature = new Pet(SUMMON_PET); spawnCreature->setActive(m_caster->isActive()); - if(spawnCreature->LoadPetFromDB(m_caster,pet_entry)) + if(m_caster->GetTypeId()==TYPEID_PLAYER && spawnCreature->LoadPetFromDB((Player*)m_caster,pet_entry)) { // set timer for unsummon int32 duration = GetSpellDuration(m_spellInfo); @@ -3203,7 +3334,8 @@ void Spell::EffectSummon(uint32 i) Map *map = m_caster->GetMap(); uint32 pet_number = objmgr.GeneratePetNumber(); - if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_spellInfo->EffectMiscValue[i], pet_number)) + if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_caster->GetPhaseMask(), + m_spellInfo->EffectMiscValue[i], pet_number)) { sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]); delete spawnCreature; @@ -3288,8 +3420,8 @@ void Spell::EffectLearnSpell(uint32 i) Player *player = (Player*)unitTarget; - uint32 spellToLearn = (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) ? damage : m_spellInfo->EffectTriggerSpell[i]; - player->learnSpell(spellToLearn); + uint32 spellToLearn = ((m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) || (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN_PET)) ? damage : m_spellInfo->EffectTriggerSpell[i]; + player->learnSpell(spellToLearn,false); sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() ); } @@ -3385,12 +3517,7 @@ void Spell::EffectDispel(uint32 i) SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first); data << uint32(spellInfo->Id); // Spell Id data << uint8(0); // 0 - dispelled !=0 cleansed - if(spellInfo->StackAmount!= 0) - { - //Why are Aura's Removed by EffIndex? Auras should be removed as a whole..... - unitTarget->RemoveSingleAuraFromStackByDispel(spellInfo->Id); - } - else + //Why are Aura's Removed by EffIndex? Auras should be removed as a whole..... unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster); } m_caster->SendMessageToSet(&data, true); @@ -3658,7 +3785,8 @@ void Spell::EffectSummonGuardian(uint32 i) Map *map = m_caster->GetMap(); uint32 pet_number = objmgr.GeneratePetNumber(); - if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_spellInfo->EffectMiscValue[i], pet_number)) + if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_caster->GetPhaseMask(), + m_spellInfo->EffectMiscValue[i], pet_number)) { sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]); delete spawnCreature; @@ -3797,7 +3925,7 @@ void Spell::EffectTradeSkill(uint32 /*i*/) // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75); } -void Spell::EffectEnchantItemPerm(uint32 i) +void Spell::EffectEnchantItemPerm(uint32 effect_idx) { if(m_caster->GetTypeId() != TYPEID_PLAYER) return; @@ -3806,37 +3934,95 @@ void Spell::EffectEnchantItemPerm(uint32 i) Player* p_caster = (Player*)m_caster; + // not grow at item use at item case p_caster->UpdateCraftSkill(m_spellInfo->Id); - if (m_spellInfo->EffectMiscValue[i]) + uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx]; + if (!enchant_id) + return; + + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + return; + + // item can be in trade slot and have owner diff. from caster + Player* item_owner = itemTarget->GetOwner(); + if(!item_owner) + return; + + if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) { - uint32 enchant_id = m_spellInfo->EffectMiscValue[i]; + sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", + p_caster->GetName(),p_caster->GetSession()->GetAccountId(), + itemTarget->GetProto()->Name1,itemTarget->GetEntry(), + item_owner->GetName(),item_owner->GetSession()->GetAccountId()); + } - SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); - if(!pEnchant) - return; + // remove old enchanting before applying new if equipped + item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false); - // item can be in trade slot and have owner diff. from caster - Player* item_owner = itemTarget->GetOwner(); - if(!item_owner) - return; + itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0); + + // add new enchanting if equipped + item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true); +} + +void Spell::EffectEnchantItemPrismatic(uint32 effect_idx) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + if (!itemTarget) + return; + + Player* p_caster = (Player*)m_caster; + + uint32 enchant_id = m_spellInfo->EffectMiscValue[effect_idx]; + if (!enchant_id) + return; + + SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id); + if(!pEnchant) + return; - if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + // support only enchantings with add socket in this slot + { + bool add_socket = false; + for(int i = 0; i < 3; ++i) { - sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", - p_caster->GetName(),p_caster->GetSession()->GetAccountId(), - itemTarget->GetProto()->Name1,itemTarget->GetEntry(), - item_owner->GetName(),item_owner->GetSession()->GetAccountId()); + if(pEnchant->type[i]==ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET) + { + add_socket = true; + break; + } } + if(!add_socket) + { + sLog.outError("Spell::EffectEnchantItemPrismatic: attempt apply enchant spell %u with SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC (%u) but without ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET (u), not suppoted yet.", + m_spellInfo->Id,SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC,ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET); + return; + } + } - // remove old enchanting before applying new if equipped - item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false); - - itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0); + // item can be in trade slot and have owner diff. from caster + Player* item_owner = itemTarget->GetOwner(); + if(!item_owner) + return; - // add new enchanting if equipped - item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true); + if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) ) + { + sLog.outCommand(p_caster->GetSession()->GetAccountId(),"GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)", + p_caster->GetName(),p_caster->GetSession()->GetAccountId(), + itemTarget->GetProto()->Name1,itemTarget->GetEntry(), + item_owner->GetName(),item_owner->GetSession()->GetAccountId()); } + + // remove old enchanting before applying new if equipped + item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,false); + + itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0); + + // add new enchanting if equipped + item_owner->ApplyEnchantment(itemTarget,PRISMATIC_ENCHANTMENT_SLOT,true); } void Spell::EffectEnchantItemTmp(uint32 i) @@ -3931,13 +4117,13 @@ void Spell::EffectEnchantItemTmp(uint32 i) else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN) duration = 1800; // 30 mins // other cases with this SpellVisual already selected - else if(m_spellInfo->SpellVisual==215) + else if(m_spellInfo->SpellVisual[0]==215) duration = 1800; // 30 mins // some fishing pole bonuses - else if(m_spellInfo->SpellVisual==563) + else if(m_spellInfo->SpellVisual[0]==563) duration = 600; // 10 mins // shaman rockbiter enchantments - else if(m_spellInfo->SpellVisual==0) + else if(m_spellInfo->SpellVisual[0]==0) duration = 1800; // 30 mins else if(m_spellInfo->Id==29702) duration = 300; // 5 mins @@ -4000,14 +4186,16 @@ void Spell::EffectTameCreature(uint32 /*i*/) creatureTarget->RemoveCorpse(); creatureTarget->SetHealth(0); // just for nice GM-mode view + uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel(); + // prepare visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); // add to world pet->GetMap()->Add((Creature*)pet); // visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()); + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); // caster have pet now m_caster->SetPet(pet); @@ -4066,7 +4254,7 @@ void Spell::EffectSummonPet(uint32 i) NewSummon->setActive(m_caster->isActive()); // petentry==0 for hunter "call pet" (current pet summoned if any) - if(NewSummon->LoadPetFromDB(m_caster,petentry)) + if(m_caster->GetTypeId() == TYPEID_PLAYER && NewSummon->LoadPetFromDB((Player*)m_caster,petentry)) { if(NewSummon->getPetType()==SUMMON_PET) { @@ -4105,7 +4293,8 @@ void Spell::EffectSummonPet(uint32 i) Map *map = m_caster->GetMap(); uint32 pet_number = objmgr.GeneratePetNumber(); - if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, petentry, pet_number)) + if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(), + petentry, pet_number)) { delete NewSummon; return; @@ -4151,10 +4340,12 @@ void Spell::EffectSummonPet(uint32 i) // this enables pet details window (Shift+P) // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later - NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); + if(m_caster->GetTypeId() == TYPEID_PLAYER) + NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); NewSummon->InitStatsForLevel(petlevel); NewSummon->InitPetCreateSpells(); + NewSummon->InitTalentForLevel(); if(NewSummon->getPetType()==SUMMON_PET) { @@ -4212,7 +4403,6 @@ void Spell::EffectLearnPetSpell(uint32 i) if(!learn_spellproto) return; - pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id)); pet->learnSpell(learn_spellproto->Id); pet->SavePetToDB(PET_SAVE_AS_CURRENT); @@ -4276,20 +4466,18 @@ void Spell::SpellDamageWeaponDmg(uint32 i) case SPELLFAMILY_WARRIOR: { // Devastate bonus and sunder armor refresh - if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508) + if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508) { uint32 stack = 0; - Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE); for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr) { SpellEntry const *proto = (*itr)->GetSpellProto(); if(proto->SpellFamilyName == SPELLFAMILY_WARRIOR - && proto->SpellFamilyFlags == SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR) + && proto->SpellFamilyFlags.IsEqual(SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR) + && (*itr)->GetCasterGUID() == m_caster->GetGUID()) { - int32 duration = GetSpellDuration(proto); - (*itr)->SetAuraDuration(duration); - (*itr)->UpdateAuraDuration(); + (*itr)->RefreshAura(); stack = (*itr)->GetStackAmount(); break; } @@ -4318,7 +4506,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) if (!spellInfo) continue; - if (spellInfo->SpellFamilyFlags == SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR + if (spellInfo->SpellFamilyFlags.IsEqual(SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR) && spellInfo->Id != m_spellInfo->Id && spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR) { @@ -4327,19 +4515,21 @@ void Spell::SpellDamageWeaponDmg(uint32 i) } } } + if (stack) + spell_bonus += stack * CalculateDamage(2, unitTarget); } break; } case SPELLFAMILY_ROGUE: { // Hemorrhage - if(m_spellInfo->SpellFamilyFlags & 0x2000000) + if(m_spellInfo->SpellFamilyFlags[0] & 0x2000000) { if(m_caster->GetTypeId()==TYPEID_PLAYER) ((Player*)m_caster)->AddComboPoints(unitTarget, 1); } // Mutilate (for each hand) - else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL) + else if(m_spellInfo->SpellFamilyFlags[1] & 0x6) { bool found = false; // fast check @@ -4367,7 +4557,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) case SPELLFAMILY_PALADIN: { // Seal of Command - receive benefit from Spell Damage and Healing - if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL) + if(m_spellInfo->SpellFamilyFlags[0] & 0x2000000) { spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo))); spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget)); @@ -4378,7 +4568,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) { // Skyshatter Harness item set bonus // Stormstrike - if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL) + if(m_spellInfo->SpellFamilyFlags[1] & 0x0010) { Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i) @@ -4396,7 +4586,7 @@ void Spell::SpellDamageWeaponDmg(uint32 i) case SPELLFAMILY_DRUID: { // Mangle (Cat): CP - if(m_spellInfo->SpellFamilyFlags==0x0000040000000000LL) + if(m_spellInfo->SpellFamilyFlags.IsEqual(0,0x00000400)) { if(m_caster->GetTypeId()==TYPEID_PLAYER) ((Player*)m_caster)->AddComboPoints(unitTarget,1); @@ -4481,33 +4671,6 @@ void Spell::SpellDamageWeaponDmg(uint32 i) // Add melee damage bonuses (also check for negative) m_caster->MeleeDamageBonus(unitTarget, &eff_damage, m_attackType, m_spellInfo); m_damage+= eff_damage; - - // take ammo - if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER) - { - Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK ); - - // wands don't have ammo - if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND) - return; - - if( pItem->GetProto()->InventoryType == INVTYPE_THROWN ) - { - if(pItem->GetMaxStackCount()==1) - { - // decrease durability for non-stackable throw weapon - ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED); - } - else - { - // decrease items amount for stackable throw weapon - uint32 count = 1; - ((Player*)m_caster)->DestroyItemCount( pItem, count, true); - } - } - else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID)) - ((Player*)m_caster)->DestroyItemCount(ammo, 1, true); - } } void Spell::EffectThreat(uint32 /*i*/) @@ -4552,7 +4715,7 @@ void Spell::EffectInterruptCast(uint32 i) { if(m_originalCaster) { - int32 duration = m_originalCaster->CalculateSpellDuration(m_spellInfo, i, unitTarget); + int32 duration = m_originalCaster->ModSpellDuration(m_spellInfo, i, unitTarget, m_originalCaster->CalcSpellDuration(m_spellInfo)); unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), duration/*GetSpellDuration(m_spellInfo)*/); } unitTarget->InterruptSpell(i,false); @@ -4584,7 +4747,7 @@ void Spell::EffectSummonObjectWild(uint32 i) Map *map = target->GetMap(); if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map, - x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) { delete pGameObj; return; @@ -4632,7 +4795,7 @@ void Spell::EffectSummonObjectWild(uint32 i) { GameObject* linkedGO = new GameObject; if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map, - x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1)) { linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0); linkedGO->SetSpellId(m_spellInfo->Id); @@ -4653,408 +4816,556 @@ void Spell::EffectScriptEffect(uint32 effIndex) { // TODO: we must implement hunter pet summon at login there (spell 6962) - // by spell id - switch(m_spellInfo->Id) + switch(m_spellInfo->SpellFamilyName) { - // PX-238 Winter Wondervolt TRAP - case 26275: + case SPELLFAMILY_GENERIC: { - if( unitTarget->HasAura(26272,0) - || unitTarget->HasAura(26157,0) - || unitTarget->HasAura(26273,0) - || unitTarget->HasAura(26274,0)) - return; + switch(m_spellInfo->Id) + { + // PX-238 Winter Wondervolt TRAP + case 26275: + { + uint32 spells[4] = { 26272, 26157, 26273, 26274 }; - uint32 iTmpSpellId; + // check presence + for(int j = 0; j < 4; ++j) + if(unitTarget->HasAura(spells[j],0)) + return; - switch(urand(0,3)) - { - case 0: - iTmpSpellId = 26272; - break; - case 1: - iTmpSpellId = 26157; - break; - case 2: - iTmpSpellId = 26273; - break; - case 3: - iTmpSpellId = 26274; - break; - } + // select spell + uint32 iTmpSpellId = spells[urand(0,3)]; - unitTarget->CastSpell(unitTarget, iTmpSpellId, true); + // cast + unitTarget->CastSpell(unitTarget, iTmpSpellId, true); + return; + } + // Bending Shinbone + case 8856: + { + if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) + return; - return; - } + uint32 spell_id = 0; + switch(urand(1,5)) + { + case 1: spell_id = 8854; break; + default: spell_id = 8855; break; + } - // Bending Shinbone - case 8856: - { - if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER) - return; + m_caster->CastSpell(m_caster,spell_id,true,NULL); + return; + } + // Brittle Armor - need remove one 24575 Brittle Armor aura + case 24590: + unitTarget->RemoveSingleSpellAurasFromStack(24575); + return; + // Mercurial Shield - need remove one 26464 Mercurial Shield aura + case 26465: + unitTarget->RemoveSingleSpellAurasFromStack(26464); + return; + // Orb teleport spells + case 25140: + case 25143: + case 25650: + case 25652: + case 29128: + case 29129: + case 35376: + case 35727: + { + if(!unitTarget) + return; - uint32 spell_id = 0; - switch(urand(1,5)) - { - case 1: spell_id = 8854; break; - default: spell_id = 8855; break; - } + uint32 spellid; + switch(m_spellInfo->Id) + { + case 25140: spellid = 32571; break; + case 25143: spellid = 32572; break; + case 25650: spellid = 30140; break; + case 25652: spellid = 30141; break; + case 29128: spellid = 32568; break; + case 29129: spellid = 32569; break; + case 35376: spellid = 25649; break; + case 35727: spellid = 35730; break; + default: + return; + } - m_caster->CastSpell(m_caster,spell_id,true,NULL); - return; - } + unitTarget->CastSpell(unitTarget,spellid,false); + return; + } + // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell) + case 22539: + case 22972: + case 22975: + case 22976: + case 22977: + case 22978: + case 22979: + case 22980: + case 22981: + case 22982: + case 22983: + case 22984: + case 22985: + { + if(!unitTarget || !unitTarget->isAlive()) + return; - // Healthstone creating spells - case 6201: - case 6202: - case 5699: - case 11729: - case 11730: - case 27230: - { - uint32 itemtype; - uint32 rank = 0; - Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) - { - if((*i)->GetId() == 18692) + // Onyxia Scale Cloak + if(unitTarget->GetDummyAura(22683)) + return; + + // Shadow Flame + m_caster->CastSpell(unitTarget, 22682, true); + return; + } + // Summon Black Qiraji Battle Tank + case 26656: { - rank = 1; + if(!unitTarget) + return; + + // Prevent stacking of mounts + unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + + // Two separate mounts depending on area id (allows use both in and out of specific instance) + if (unitTarget->GetAreaId() == 3428) + unitTarget->CastSpell(unitTarget, 25863, false); + else + unitTarget->CastSpell(unitTarget, 26655, false); break; } - else if((*i)->GetId() == 18693) + // Piccolo of the Flaming Fire + case 17512: { - rank = 2; + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; + unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); break; } - } + // Mirren's Drinking Hat + case 29830: + { + uint32 item = 0; + switch ( urand(1,6) ) + { + case 1:case 2:case 3: + item = 23584;break; // Loch Modan Lager + case 4:case 5: + item = 23585;break; // Stouthammer Lite + case 6: + item = 23586;break; // Aerie Peak Pale Ale + } + if (item) + DoCreateItem(effIndex,item); + break; + } + // Improved Sprint + case 30918: + { + // Removes snares and roots. + uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE); + Unit::AuraMap& Auras = unitTarget->GetAuras(); + for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + { + next = iter; + ++next; + Aura *aur = iter->second; + if (!aur->IsPositive()) //only remove negative spells + { + // check for mechanic mask + if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask) + { + unitTarget->RemoveAurasDueToSpell(aur->GetId()); + if(Auras.empty()) + break; + else + next = Auras.begin(); + } + } + } + break; + } + /*// Flame Crash + case 41126: + { + if(!unitTarget) + return; - static uint32 const itypes[6][3] = { - { 5512,19004,19005}, // Minor Healthstone - { 5511,19006,19007}, // Lesser Healthstone - { 5509,19008,19009}, // Healthstone - { 5510,19010,19011}, // Greater Healthstone - { 9421,19012,19013}, // Major Healthstone - {22103,22104,22105} // Master Healthstone - }; + unitTarget->CastSpell(unitTarget, 41131, true); + break; + }*/ + // Draw Soul + case 40904: + { + if(!unitTarget) + return; - switch(m_spellInfo->Id) - { - case 6201: itemtype=itypes[0][rank];break; // Minor Healthstone - case 6202: itemtype=itypes[1][rank];break; // Lesser Healthstone - case 5699: itemtype=itypes[2][rank];break; // Healthstone - case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone - case 11730: itemtype=itypes[4][rank];break; // Major Healthstone - case 27230: itemtype=itypes[5][rank];break; // Master Healthstone - default: - return; - } - DoCreateItem( effIndex, itemtype ); - return; - } - // Brittle Armor - need remove one 24575 Brittle Armor aura - case 24590: - unitTarget->RemoveSingleAuraFromStack(24575, 0); - unitTarget->RemoveSingleAuraFromStack(24575, 1); - return; - // Mercurial Shield - need remove one 26464 Mercurial Shield aura - case 26465: - unitTarget->RemoveSingleAuraFromStack(26464, 0); - return; - // Orb teleport spells - case 25140: - case 25143: - case 25650: - case 25652: - case 29128: - case 29129: - case 35376: - case 35727: - { - if(!unitTarget) - return; + unitTarget->CastSpell(m_caster, 40903, true); + break; + } + case 41931: + { + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; - uint32 spellid; - switch(m_spellInfo->Id) - { - case 25140: spellid = 32571; break; - case 25143: spellid = 32572; break; - case 25650: spellid = 30140; break; - case 25652: spellid = 30141; break; - case 29128: spellid = 32568; break; - case 29129: spellid = 32569; break; - case 35376: spellid = 25649; break; - case 35727: spellid = 35730; break; - default: - return; - } + int bag=19; + int slot=0; + Item* item = NULL; + + while (bag < 256) + { + item = ((Player*)m_caster)->GetItemByPos(bag,slot); + if (item && item->GetEntry() == 38587) break; + slot++; + if (slot == 39) + { + slot = 0; + bag++; + } + } + if (bag < 256) + { + if (((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount() == 1) ((Player*)m_caster)->RemoveItem(bag,slot,true); + else ((Player*)m_caster)->GetItemByPos(bag,slot)->SetCount(((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount()-1); + // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen) + m_caster->CastSpell(m_caster,42518,true); + return; + } + break; + } + // Force Cast - Portal Effect: Sunwell Isle + case 44876: + { + if(!unitTarget) + return; - unitTarget->CastSpell(unitTarget,spellid,false); - return; - } + unitTarget->CastSpell(unitTarget, 44870, true); + break; + } + // Goblin Weather Machine + case 46203: + { + if(!unitTarget) + return; - // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell) - case 22539: - case 22972: - case 22975: - case 22976: - case 22977: - case 22978: - case 22979: - case 22980: - case 22981: - case 22982: - case 22983: - case 22984: - case 22985: - { - if(!unitTarget || !unitTarget->isAlive()) - return; + uint32 spellId; + switch(rand()%4) + { + case 0: spellId = 46740; break; + case 1: spellId = 46739; break; + case 2: spellId = 46738; break; + case 3: spellId = 46736; break; + } + unitTarget->CastSpell(unitTarget, spellId, true); + break; + } + //5,000 Gold + case 46642: + { + if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) + return; - // Onyxia Scale Cloak - if(unitTarget->GetDummyAura(22683)) - return; + ((Player*)unitTarget)->ModifyMoney(50000000); - // Shadow Flame - m_caster->CastSpell(unitTarget, 22682, true); - return; - } - break; + break; + } + // Emblazon Runeblade + case 51770: + { + if(!unitTarget) + return; - // Summon Black Qiraji Battle Tank - case 26656: - { - if(!unitTarget) - return; + unitTarget->CastSpell(unitTarget,51771,false); + break; + } + // Death Gate + case 52751: + { + if(!unitTarget || unitTarget->getClass() != CLASS_DEATH_KNIGHT) + return; + // triggered spell is stored in m_spellInfo->EffectBasePoints[0] + unitTarget->CastSpell(unitTarget, damage, false); + break; + } + // random spell learn instead placeholder + case 60893: // Northrend Alchemy Research + case 61177: // Northrend Inscription Research + case 61288: // Minor Inscription Research + case 61756: // Northrend Inscription Research (FAST QA VERSION) + { + if(!IsExplicitDiscoverySpell(m_spellInfo)) + { + sLog.outError("Wrong explicit discovery spell %u structure, or outdated...",m_spellInfo->Id); + return; + } - // Prevent stacking of mounts - unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + if(m_caster->GetTypeId()!=TYPEID_PLAYER) + return; + Player* player = (Player*)m_caster; - // Two separate mounts depending on area id (allows use both in and out of specific instance) - if (unitTarget->GetAreaId() == 3428) - unitTarget->CastSpell(unitTarget, 25863, false); - else - unitTarget->CastSpell(unitTarget, 26655, false); - break; - } - // Piccolo of the Flaming Fire - case 17512: - { - if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE); - break; - } - // Netherbloom - case 28702: - { - if(!unitTarget) - return; - // 25% chance of casting a random buff - if(roll_chance_i(75)) - return; + // need replace effect 0 item by loot + uint32 reagent_id = m_spellInfo->EffectItemType[0]; - // triggered spells are 28703 to 28707 - // Note: some sources say, that there was the possibility of - // receiving a debuff. However, this seems to be removed by a patch. - const uint32 spellid = 28703; + if(!player->HasItemCount(reagent_id,1)) + return; - // don't overwrite an existing aura - for(uint8 i=0; i<5; i++) - if(unitTarget->HasAura(spellid+i, 0)) - return; - unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true); - break; - } + // remove reagent + uint32 count = 1; + player->DestroyItemCount (reagent_id,count,true); - // Nightmare Vine - case 28720: - { - if(!unitTarget) - return; - // 25% chance of casting Nightmare Pollen - if(roll_chance_i(75)) - return; - unitTarget->CastSpell(unitTarget, 28721, true); - break; - } + // create some random items + player->AutoStoreLoot(m_spellInfo->Id,LootTemplates_Spell); - // Mirren's Drinking Hat - case 29830: - { - uint32 item = 0; - switch ( urand(1,6) ) - { - case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager - case 4: case 5: item = 23585; break;// Stouthammer Lite - case 6: item = 23586; break;// Aerie Peak Pale Ale + // learn random explicit discovery recipe (if any) + if(uint32 discoveredSpell = GetExplicitDiscoverySpell(m_spellInfo->Id, player)) + player->learnSpell(discoveredSpell,false); + return; + } } - if (item) - DoCreateItem(effIndex,item); break; } - // Improved Sprint - case 30918: + case SPELLFAMILY_WARLOCK: { - // Removes snares and roots. - uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE); - Unit::AuraMap& Auras = unitTarget->GetAuras(); - for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next) + switch(m_spellInfo->Id) { - next = iter; - ++next; - Aura *aur = iter->second; - if (!aur->IsPositive()) //only remove negative spells + // Healthstone creating spells + case 6201: + case 6202: + case 5699: + case 11729: + case 11730: + case 27230: + case 47871: + case 47878: { - // check for mechanic mask - if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask) + uint32 itemtype; + uint32 rank = 0; + Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) { - unitTarget->RemoveAurasDueToSpell(aur->GetId()); - if(Auras.empty()) + if((*i)->GetId() == 18692) + { + rank = 1; break; - else - next = Auras.begin(); + } + else if((*i)->GetId() == 18693) + { + rank = 2; + break; + } + } + + static uint32 const itypes[8][3] = { + { 5512,19004,19005}, // Minor Healthstone + { 5511,19006,19007}, // Lesser Healthstone + { 5509,19008,19009}, // Healthstone + { 5510,19010,19011}, // Greater Healthstone + { 9421,19012,19013}, // Major Healthstone + {22103,22104,22105}, // Master Healthstone + {36889,36890,36891}, // Demonic Healthstone + {36892,36893,36894} // Fel Healthstone + }; + + switch(m_spellInfo->Id) + { + case 6201: + itemtype=itypes[0][rank];break; // Minor Healthstone + case 6202: + itemtype=itypes[1][rank];break; // Lesser Healthstone + case 5699: + itemtype=itypes[2][rank];break; // Healthstone + case 11729: + itemtype=itypes[3][rank];break; // Greater Healthstone + case 11730: + itemtype=itypes[4][rank];break; // Major Healthstone + case 27230: + itemtype=itypes[5][rank];break; // Master Healthstone + case 47871: + itemtype=itypes[6][rank];break; // Demonic Healthstone + case 47878: + itemtype=itypes[7][rank];break; // Fel Healthstone + default: + return; } + DoCreateItem( effIndex, itemtype ); + return; } } break; } - - // Goblin Weather Machine - case 46203: + case SPELLFAMILY_PRIEST: { - if(!unitTarget) - return; - - uint32 spellId; - switch(rand()%4) + switch(m_spellInfo->Id) { - case 0: - spellId=46740; - break; - case 1: - spellId=46739; - break; - case 2: - spellId=46738; - break; - case 3: - spellId=46736; + // Pain and Suffering + case 47948: + { + if (!unitTarget) + return; + // Refresh Shadow Word: Pain on target + Unit::AuraMap& auras = unitTarget->GetAuras(); + for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr) + { + SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); + if( spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && + spellInfo->SpellFamilyFlags[0] & 0x8000 && + (*itr).second->GetCasterGUID() == m_caster->GetGUID()) + { + (*itr).second->RefreshAura(); + return; + } + } + return; + } + default: break; } - unitTarget->CastSpell(unitTarget, spellId, true); break; } - - } - - if(!unitTarget || !unitTarget->isAlive()) // can we remove this check? - { - sLog.outError("Spell %u in EffectScriptEffect does not have unitTarget", m_spellInfo->Id); - return; - } - - switch(m_spellInfo->Id) - { - // Dreaming Glory - case 28698: unitTarget->CastSpell(unitTarget, 28694, true); break; - // Needle Spine - //case 39835: unitTarget->CastSpell(unitTarget, 39968, true); break; - // Draw Soul - case 40904: unitTarget->CastSpell(m_caster, 40903, true); break; - // Flame Crash - //case 41126: unitTarget->CastSpell(unitTarget, 41131, true); break; - case 41931: + case SPELLFAMILY_HUNTER: { - int bag=19; - int slot=0; - Item* item = NULL; - - while (bag < 256) + switch(m_spellInfo->Id) { - item = ((Player*)m_caster)->GetItemByPos(bag,slot); - if (item && item->GetEntry() == 38587) break; - slot++; - if (slot == 39) + // Chimera Shot + case 53209: { - slot = 0; - bag++; + uint32 spellId = 0; + int32 basePoint = 0; + Unit::AuraMap& Auras = unitTarget->GetAuras(); + for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i) + { + Aura *aura = (*i).second; + if (aura->GetCasterGUID() != m_caster->GetGUID()) + continue; + // Search only Serpent Sting, Viper Sting, Scorpid Sting auras + uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags; + if (!(familyFlag & 0x000000800000C000LL)) + continue; + // Refresh aura duration + aura->RefreshAura(); + + // Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting. + if (familyFlag & 0x0000000000004000LL && aura->GetEffIndex() == 0) + { + spellId = 53353; // 53353 Chimera Shot - Serpent + basePoint = aura->GetModifier()->m_amount * 5 * 40 / 100; + } + // Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting. + if (familyFlag & 0x0000008000000000LL && aura->GetEffIndex() == 0) + { + spellId = 53358; // 53358 Chimera Shot - Viper + basePoint = aura->GetModifier()->m_amount * 4 * 60 / 100; + } + // Scorpid Sting - Attempts to Disarm the target for 10 sec. This effect cannot occur more than once per 1 minute. + if (familyFlag & 0x0000000000008000LL) + spellId = 53359; // 53359 Chimera Shot - Scorpid + // ?? nothing say in spell desc (possibly need addition check) + //if (familyFlag & 0x0000010000000000LL || // dot + // familyFlag & 0x0000100000000000LL) // stun + //{ + // spellId = 53366; // 53366 Chimera Shot - Wyvern + //} + } + if (spellId) + m_caster->CastCustomSpell(unitTarget, spellId, &basePoint, 0, 0, false); + return; } + default: + break; } - if (bag < 256) - { - if (((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount() == 1) ((Player*)m_caster)->RemoveItem(bag,slot,true); - else ((Player*)m_caster)->GetItemByPos(bag,slot)->SetCount(((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount()-1); - // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen) - m_caster->CastSpell(m_caster,42518,true); - return; - } - } - // Force Cast - Portal Effect: Sunwell Isle - case 44876: unitTarget->CastSpell(unitTarget, 44870, true); break; - //5,000 Gold - case 46642: - { - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - ((Player*)unitTarget)->ModifyMoney(50000000); break; } - } - - if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN ) - { - switch(m_spellInfo->SpellFamilyFlags) + case SPELLFAMILY_PALADIN: { // Judgement - case 0x800000: + if (m_spellInfo->SpellFamilyFlags[0] & 0x800000) { + if(!unitTarget || !unitTarget->isAlive()) + return; + uint32 spellId1 = 0; uint32 spellId2 = 0; - // all seals have aura dummy + // Judgement self add switch + switch (m_spellInfo->Id) + { + case 41467: break; // Judgement + case 53407: spellId1 = 20184; break; // Judgement of Justice + case 20271: // Judgement of Light + case 57774: spellId1 = 20185; break; // Judgement of Light + case 53408: spellId1 = 20186; break; // Judgement of Wisdom + default: + return; + } + // all seals have aura dummy in 2 effect Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr) { SpellEntry const *spellInfo = (*itr)->GetSpellProto(); - // search seal (all seals have judgement's aura dummy spell id in 2 effect - if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 ) + if ((*itr)->GetEffIndex() != 2 || !spellInfo || !IsSealSpell(spellInfo)) continue; - - // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE - spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1; - - if(spellId2 <= 1) + spellId2 = (*itr)->GetModifier()->m_amount; + SpellEntry const *judge = sSpellStore.LookupEntry(spellId2); + if (!judge) continue; + break; + } + if (spellId1) + m_caster->CastSpell(unitTarget, spellId1, true); + if (spellId2) + m_caster->CastSpell(unitTarget, spellId2, true); + return; + } + } + case SPELLFAMILY_POTION: + { + switch(m_spellInfo->Id) + { + // Dreaming Glory + case 28698: + { + if(!unitTarget) + return; + unitTarget->CastSpell(unitTarget, 28694, true); + break; + } + // Netherbloom + case 28702: + { + if(!unitTarget) + return; + // 25% chance of casting a random buff + if(roll_chance_i(75)) + return; - // found, remove seal - m_caster->RemoveAurasDueToSpell((*itr)->GetId()); - - // Sanctified Judgement - Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY); - for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i) - { - if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL) - { - int32 chance = (*i)->GetModifier()->m_amount; - if ( roll_chance_i(chance) ) - { - int32 mana = spellInfo->manaCost; - if ( Player* modOwner = m_caster->GetSpellModOwner() ) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana); - mana = int32(mana* 0.8f); - m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i); - } - break; - } - } + // triggered spells are 28703 to 28707 + // Note: some sources say, that there was the possibility of + // receiving a debuff. However, this seems to be removed by a patch. + const uint32 spellid = 28703; + // don't overwrite an existing aura + for(uint8 i=0; i<5; i++) + if(unitTarget->HasAura(spellid+i, 0)) + return; + unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true); break; } - m_caster->CastSpell(unitTarget,spellId2,true); - return; + // Nightmare Vine + case 28720: + { + if(!unitTarget) + return; + // 25% chance of casting Nightmare Pollen + if(roll_chance_i(75)) + return; + unitTarget->CastSpell(unitTarget, 28721, true); + break; + } } + break; } } @@ -5070,7 +5381,7 @@ void Spell::EffectSanctuary(uint32 /*i*/) std::list<Unit*> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(unitTarget, unitTarget, World::GetMaxVisibleDistance()); - Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(targets, u_check); + Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(unitTarget, targets, u_check); unitTarget->VisitNearbyObject(World::GetMaxVisibleDistance(), searcher); for(std::list<Unit*>::iterator iter = targets.begin(); iter != targets.end(); ++iter) { @@ -5090,7 +5401,7 @@ void Spell::EffectSanctuary(uint32 /*i*/) unitTarget->CombatStop(); unitTarget->getHostilRefManager().deleteReferences(); // stop all fighting // Vanish allows to remove all threat and cast regular stealth so other spells can be used - if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH)) + if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags[0] & SPELLFAMILYFLAG_ROGUE_VANISH)) { ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); } @@ -5125,6 +5436,7 @@ void Spell::EffectDuel(uint32 i) // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities) // Don't have to check the target's map since you cannot challenge someone across maps if(caster->GetMap()->Instanceable()) + //if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609) { SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here return; @@ -5150,7 +5462,8 @@ void Spell::EffectDuel(uint32 i) uint32 gameobject_id = m_spellInfo->EffectMiscValue[i]; Map *map = m_caster->GetMap(); - if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map, + if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, + map, m_caster->GetPhaseMask(), m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 , m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 , m_caster->GetPositionZ(), @@ -5263,6 +5576,43 @@ void Spell::EffectActivateObject(uint32 effect_idx) sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget); } +void Spell::EffectApplyGlyph(uint32 i) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *player = (Player*)m_caster; + + // remove old glyph + if(uint32 oldglyph = player->GetGlyph(m_glyphIndex)) + { + if(GlyphPropertiesEntry const *old_gp = sGlyphPropertiesStore.LookupEntry(oldglyph)) + { + player->RemoveAurasDueToSpell(old_gp->SpellId); + player->SetGlyph(m_glyphIndex, 0); + } + } + + // apply new one + if(uint32 glyph = m_spellInfo->EffectMiscValue[i]) + { + if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph)) + { + if(GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(m_glyphIndex))) + { + if(gp->TypeFlags != gs->TypeFlags) + { + SendCastResult(SPELL_FAILED_INVALID_GLYPH); + return; // glyph slot missmatch + } + } + + player->CastSpell(m_caster, gp->SpellId, true); + player->SetGlyph(m_glyphIndex, glyph); + } + } +} + void Spell::EffectSummonTotem(uint32 i) { uint8 slot = 0; @@ -5296,7 +5646,8 @@ void Spell::EffectSummonTotem(uint32 i) Totem* pTotem = new Totem; - if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team )) + if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_caster->GetPhaseMask(), + m_spellInfo->EffectMiscValue[i], team )) { delete pTotem; return; @@ -5331,10 +5682,9 @@ void Spell::EffectSummonTotem(uint32 i) } pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id); - pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); - pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true); - pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true); + if(m_caster->GetTypeId() == TYPEID_PLAYER) + pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE); pTotem->Summon(m_caster); @@ -5429,7 +5779,8 @@ void Spell::EffectFeedPet(uint32 i) Player *_player = (Player*)m_caster; - if(!itemTarget) + Item* foodItem = m_targets.getItemTarget(); + if(!foodItem) return; Pet *pet = _player->GetPet(); @@ -5439,15 +5790,15 @@ void Spell::EffectFeedPet(uint32 i) if(!pet->isAlive()) return; - int32 benefit = pet->GetCurrentFoodBenefitLevel(itemTarget->GetProto()->ItemLevel); + int32 benefit = pet->GetCurrentFoodBenefitLevel(foodItem->GetProto()->ItemLevel); if(benefit <= 0) return; uint32 count = 1; - _player->DestroyItemCount(itemTarget,count,true); + _player->DestroyItemCount(foodItem,count,true); // TODO: fix crash when a spell has two effects, both pointed at the same item target - m_caster->CastCustomSpell(m_caster,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true); + m_caster->CastCustomSpell(pet,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true); } void Spell::EffectDismissPet(uint32 /*i*/) @@ -5507,7 +5858,8 @@ void Spell::EffectSummonObject(uint32 i) m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE); Map *map = m_caster->GetMap(); - if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1)) + if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, + m_caster->GetPhaseMask(), x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1)) { delete pGameObj; return; @@ -5586,18 +5938,14 @@ void Spell::EffectAddExtraAttacks(uint32 /*i*/) void Spell::EffectParry(uint32 /*i*/) { - if (unitTarget->GetTypeId() == TYPEID_PLAYER) - { + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) ((Player*)unitTarget)->SetCanParry(true); - } } void Spell::EffectBlock(uint32 /*i*/) { - if (unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)unitTarget)->SetCanBlock(true); + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->SetCanBlock(true); } void Spell::EffectMomentMove(uint32 i) @@ -5808,8 +6156,8 @@ void Spell::EffectSummonCritter(uint32 i) Map *map = m_caster->GetMap(); uint32 pet_number = objmgr.GeneratePetNumber(); - if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), - map, pet_entry, pet_number)) + if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, m_caster->GetPhaseMask(), + pet_entry, pet_number)) { sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry); delete critter; @@ -5889,14 +6237,16 @@ void Spell::EffectKnockBack(uint32 i) float vsin = dx / dist; float vcos = dy / dist; + float speedxy = float(m_spellInfo->EffectMiscValue[i])/10; + float speedz = float(damage/-10); WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4)); data.append(unitTarget->GetPackGUID()); data << uint32(0); // Sequence data << float(vcos); // x direction data << float(vsin); // y direction - data << float(m_spellInfo->EffectMiscValue[i])/10; // Horizontal speed - data << float(damage/-10); // Z Movement speed (vertical) + data << float(speedxy); // Horizontal speed + data << float(speedz); // Z Movement speed (vertical) ((Player*)unitTarget)->GetSession()->SendPacket(&data); } @@ -5919,17 +6269,26 @@ void Spell::EffectSendTaxi(uint32 i) uint32 mountid = 0; switch(m_spellInfo->Id) { - case 31606: //Stormcrow Amulet + case 31606: //Stormcrow Amulet mountid = 17447; break; - case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run - case 45113: //Quest - Sunwell Daily - Ship Bombing Run - case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return + case 45071: //Quest - Sunwell Daily - Dead Scar Bombing Run + case 45113: //Quest - Sunwell Daily - Ship Bombing Run + case 45353: //Quest - Sunwell Daily - Ship Bombing Run Return mountid = 22840; break; - case 34905: //Stealth Flight + case 34905: //Stealth Flight mountid = 6851; break; + case 45883: //Amber Ledge to Beryl Point + mountid = 23524; + break; + case 46064: //Amber Ledge to Coldarra + mountid = 6371; + break; + case 53335: //Stormwind Harbor Flight - Peaceful + mountid = 6852; + break; case 41533: //Fly of the Netherwing case 41540: //Fly of the Netherwing mountid = 23468; @@ -6151,7 +6510,7 @@ void Spell::EffectTransmitted(uint32 effIndex) GameObject* pGameObj = new GameObject; if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap, - fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) { delete pGameObj; return; @@ -6165,9 +6524,9 @@ void Spell::EffectTransmitted(uint32 effIndex) { m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID()); // Orientation3 - pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 ); + pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 2, 0.88431775569915771 ); // Orientation4 - pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 ); + pGameObj->SetFloatValue(GAMEOBJECT_PARENTROTATION + 3, -0.4668855369091033 ); m_caster->AddGameObject(pGameObj); // will removed at spell cancel // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo)) @@ -6222,7 +6581,7 @@ void Spell::EffectTransmitted(uint32 effIndex) { GameObject* linkedGO = new GameObject; if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap, - fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) + m_caster->GetPhaseMask(), fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1)) { linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0); linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() ); @@ -6262,6 +6621,28 @@ void Spell::EffectProspecting(uint32 /*i*/) ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING); } +void Spell::EffectMilling(uint32 /*i*/) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player* p_caster = (Player*)m_caster; + if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_HERBS)) + return; + + if(itemTarget->GetCount() < 5) + return; + + if( sWorld.getConfig(CONFIG_SKILL_MILLING)) + { + uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_INSCRIPTION); + uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank; + p_caster->UpdateGatherSkill(SKILL_INSCRIPTION, SkillValue, reqSkillValue); + } + + ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_MILLING); +} + void Spell::EffectSkill(uint32 /*i*/) { sLog.outDebug("WORLD: SkillEFFECT"); @@ -6409,8 +6790,42 @@ void Spell::EffectQuestFail(uint32 i) ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]); } +void Spell::EffectActivateRune(uint32 eff_idx) +{ + if(m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + Player *plr = (Player*)m_caster; + + if(plr->getClass() != CLASS_DEATH_KNIGHT) + return; + + for(uint32 j = 0; j < MAX_RUNES; ++j) + { + if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[eff_idx]) + { + plr->SetRuneCooldown(j, 0); + } + } +} + +void Spell::EffectTitanGrip(uint32 /*eff_idx*/) +{ + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->SetCanTitanGrip(true); +} + void Spell::EffectRedirectThreat(uint32 /*i*/) { if(unitTarget) m_caster->SetReducedThreatPercent((uint32)damage, unitTarget->GetGUID()); } + +void Spell::EffectRenamePet(uint32 /*eff_idx*/) +{ + if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || + !((Creature*)unitTarget)->isPet() || ((Pet*)unitTarget)->getPetType() != HUNTER_PET) + return; + + unitTarget->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_ALLOWED); +} diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index 940135e2db5..676bb6a2dae 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,17 +38,19 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) { // TODO: add targets.read() check - CHECK_PACKET_SIZE(recvPacket,1+1+1+1+8); + CHECK_PACKET_SIZE(recvPacket,1+1+1+4+8+4+1); Player* pUser = _player; uint8 bagIndex, slot; - uint8 spell_count; // number of spells at item, not used + uint8 unk_flags; // flags (if 0x02 - some additional data are received) uint8 cast_count; // next cast if exists (single or not) uint64 item_guid; + uint32 glyphIndex; // something to do with glyphs? + uint32 spellid; // casted spell id - recvPacket >> bagIndex >> slot >> spell_count >> cast_count >> item_guid; + recvPacket >> bagIndex >> slot >> cast_count >> spellid >> item_guid >> glyphIndex >> unk_flags; - Item *pItem = pUser->GetItemByPos(bagIndex, slot); + Item *pItem = pUser->GetUseableItemByPos(bagIndex, slot); if(!pItem) { pUser->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); @@ -61,7 +63,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) return; } - sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, spell_count: %u , cast_count: %u, Item: %u, data length = %i", bagIndex, slot, spell_count, cast_count, pItem->GetEntry(), recvPacket.size()); + sLog.outDetail("WORLD: CMSG_USE_ITEM packet, bagIndex: %u, slot: %u, cast_count: %u, spellid: %u, Item: %u, glyphIndex: %u, unk_flags: %u, data length = %i", bagIndex, slot, cast_count, spellid, pItem->GetEntry(), glyphIndex, unk_flags, recvPacket.size()); ItemPrototype const *proto = pItem->GetProto(); if(!proto) @@ -126,57 +128,7 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) if(!Script->ItemUse(pUser,pItem,targets)) { // no script or script not process request by self - - // special learning case - if(pItem->GetProto()->Spells[0].SpellId==SPELL_ID_GENERIC_LEARN) - { - uint32 learning_spell_id = pItem->GetProto()->Spells[1].SpellId; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(SPELL_ID_GENERIC_LEARN); - if(!spellInfo) - { - sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, SPELL_ID_GENERIC_LEARN); - pUser->SendEquipError(EQUIP_ERR_NONE,pItem,NULL); - return; - } - - Spell *spell = new Spell(pUser, spellInfo, false); - spell->m_CastItem = pItem; - spell->m_cast_count = cast_count; //set count of casts - spell->m_currentBasePoints[0] = learning_spell_id; - spell->prepare(&targets); - return; - } - - // use triggered flag only for items with many spell casts and for not first cast - int count = 0; - - for(int i = 0; i < 5; ++i) - { - _Spell const& spellData = pItem->GetProto()->Spells[i]; - - // no spell - if(!spellData.SpellId) - continue; - - // wrong triggering type - if( spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_USE && spellData.SpellTrigger != ITEM_SPELLTRIGGER_ON_NO_DELAY_USE) - continue; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellData.SpellId); - if(!spellInfo) - { - sLog.outError("Item (Entry: %u) in have wrong spell id %u, ignoring ",proto->ItemId, spellData.SpellId); - continue; - } - - Spell *spell = new Spell(pUser, spellInfo, (count > 0)); - spell->m_CastItem = pItem; - spell->m_cast_count = cast_count; //set count of casts - spell->prepare(&targets); - - ++count; - } + pUser->CastItemUseSpell(pItem,targets,cast_count,glyphIndex); } } @@ -227,7 +179,7 @@ void WorldSession::HandleOpenItemOpcode(WorldPacket& recvPacket) } // required picklocking - if(lockInfo->requiredlockskill || lockInfo->requiredminingskill) + if(lockInfo->Skill[1] || lockInfo->Skill[0]) { pUser->SendEquipError(EQUIP_ERR_ITEM_LOCKED, pItem, NULL ); return; @@ -281,17 +233,28 @@ void WorldSession::HandleGameObjectUseOpcode( WorldPacket & recv_data ) obj->Use(_player); } +void WorldSession::HandleGameobjectReportUse(WorldPacket& recvPacket) +{ + CHECK_PACKET_SIZE(recvPacket,8); + + uint64 guid; + recvPacket >> guid; + + sLog.outDebug( "WORLD: Recvd CMSG_GAMEOBJ_REPORT_USE Message [in game guid: %u]", GUID_LOPART(guid)); +} + void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { - CHECK_PACKET_SIZE(recvPacket,4+1+2); + CHECK_PACKET_SIZE(recvPacket,1+4+1); uint32 spellId; - uint8 cast_count; - recvPacket >> spellId; + uint8 cast_count, unk_flags; recvPacket >> cast_count; + recvPacket >> spellId; + recvPacket >> unk_flags; // flags (if 0x02 - some additional data are received) - sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u data length = %i", - spellId, cast_count, recvPacket.size()); + sLog.outDebug("WORLD: got cast spell packet, spellId - %u, cast_count: %u, unk_flags %u, data length = %i", + spellId, cast_count, unk_flags, recvPacket.size()); SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId ); @@ -301,8 +264,8 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) return; } - // not have spell or spell passive and not casted by client - if ( !_player->HasSpell (spellId) || IsPassiveSpell(spellId) ) + // not have spell in spellbook or spell passive and not casted by client + if ( !_player->HasActiveSpell (spellId) || IsPassiveSpell(spellId) ) { //cheater? kick? ban? return; @@ -334,9 +297,12 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket) { - CHECK_PACKET_SIZE(recvPacket,4); + CHECK_PACKET_SIZE(recvPacket,5); + // increments with every CANCEL packet, don't use for now + uint8 counter; uint32 spellId; + recvPacket >> counter; recvPacket >> spellId; //FIXME: hack, ignore unexpected client cancel Deadly Throw cast @@ -363,7 +329,7 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket) return; // lifebloom must delete final heal effect - if (spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && (spellInfo->SpellFamilyFlags & 0x1000000000LL) ) + if (spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && (spellInfo->SpellFamilyFlags[1] & 0x10) ) { Unit::AuraMap::iterator iter; while((iter = _player->m_Auras.find(Unit::spellEffectPair(spellId, 1))) != _player->m_Auras.end()) @@ -420,7 +386,7 @@ void WorldSession::HandlePetCancelAuraOpcode( WorldPacket& recvPacket) return; } - Creature* pet=ObjectAccessor::GetCreatureOrPet(*_player,guid); + Creature* pet=ObjectAccessor::GetCreatureOrPetOrVehicle(*_player,guid); if(!pet) { diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 435481de949..847f90ed0c9 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #include "World.h" #include "Chat.h" #include "Spell.h" +#include "BattleGroundMgr.h" bool IsAreaEffectTarget[TOTAL_SPELL_TARGETS]; @@ -38,25 +39,25 @@ SpellMgr::SpellMgr() case SPELL_EFFECT_PERSISTENT_AREA_AURA: //27 case SPELL_EFFECT_SUMMON: //28 case SPELL_EFFECT_TRIGGER_MISSILE: //32 - case SPELL_EFFECT_SUMMON_WILD: //41 - case SPELL_EFFECT_SUMMON_GUARDIAN: //42 + //case SPELL_EFFECT_SUMMON_WILD: //41 not 303 + //case SPELL_EFFECT_SUMMON_GUARDIAN: //42 not 303 case SPELL_EFFECT_TRANS_DOOR: //50 summon object case SPELL_EFFECT_SUMMON_PET: //56 case SPELL_EFFECT_ADD_FARSIGHT: //72 - case SPELL_EFFECT_SUMMON_POSSESSED: //73 - case SPELL_EFFECT_SUMMON_TOTEM: //74 + //case SPELL_EFFECT_SUMMON_POSSESSED: //73 + //case SPELL_EFFECT_SUMMON_TOTEM: //74 case SPELL_EFFECT_SUMMON_OBJECT_WILD: //76 - case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: //87 - case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: //88 - case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: //89 - case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: //90 - case SPELL_EFFECT_SUMMON_CRITTER: //97 + //case SPELL_EFFECT_SUMMON_TOTEM_SLOT1: //87 + //case SPELL_EFFECT_SUMMON_TOTEM_SLOT2: //88 + //case SPELL_EFFECT_SUMMON_TOTEM_SLOT3: //89 + //case SPELL_EFFECT_SUMMON_TOTEM_SLOT4: //90 + //case SPELL_EFFECT_SUMMON_CRITTER: //97 not 303 case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: //104 case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: //105 case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: //106 case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: //107 case SPELL_EFFECT_SUMMON_DEAD_PET: //109 - case SPELL_EFFECT_SUMMON_DEMON: //112 + //case SPELL_EFFECT_SUMMON_DEMON: //112 not 303 case SPELL_EFFECT_TRIGGER_SPELL_2: //151 ritual of summon EffectTargetType[i] = SPELL_REQUIRE_DEST; break; @@ -105,7 +106,6 @@ SpellMgr::SpellMgr() case TARGET_UNIT_TARGET_ALLY: case TARGET_UNIT_TARGET_RAID: case TARGET_UNIT_TARGET_ANY: - case TARGET_UNIT_SINGLE_UNKNOWN: case TARGET_UNIT_TARGET_ENEMY: case TARGET_UNIT_TARGET_PARTY: case TARGET_UNIT_PARTY_TARGET: @@ -244,19 +244,8 @@ uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell) int32 castTime = spellCastTimeEntry->CastTime; - if (spell) - { - if(Player* modOwner = spell->GetCaster()->GetSpellModOwner()) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell); - - if( !(spellInfo->Attributes & (SPELL_ATTR_UNK4|SPELL_ATTR_UNK5)) ) - castTime = int32(castTime * spell->GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED)); - else - { - if (spell->IsRangedSpell() && !spell->IsAutoRepeat()) - castTime = int32(castTime * spell->GetCaster()->m_modAttackSpeedPct[RANGED_ATTACK]); - } - } + if (spell && spell->GetCaster()) + spell->GetCaster()->ModSpellCastTime(spellInfo, castTime); if (spellInfo->Attributes & SPELL_ATTR_RANGED && (!spell || !(spell->IsAutoRepeat()))) castTime += 500; @@ -328,17 +317,17 @@ SpellSpecific GetSpellSpecific(uint32 spellId) case SPELLFAMILY_MAGE: { // family flags 18(Molten), 25(Frost/Ice), 28(Mage) - if (spellInfo->SpellFamilyFlags & 0x12040000) + if (spellInfo->SpellFamilyFlags[0] & 0x12040000) return SPELL_MAGE_ARMOR; - if ((spellInfo->SpellFamilyFlags & 0x1000000) && spellInfo->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE) + if ((spellInfo->SpellFamilyFlags[0] & 0x1000000) && spellInfo->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE) return SPELL_MAGE_POLYMORPH; break; } case SPELLFAMILY_WARRIOR: { - if (spellInfo->SpellFamilyFlags & 0x00008000010000LL) + if (spellInfo->SpellFamilyFlags[1] & 0x000080 || spellInfo->SpellFamilyFlags[0] & 0x10000LL) return SPELL_POSITIVE_SHOUT; break; @@ -349,12 +338,12 @@ SpellSpecific GetSpellSpecific(uint32 spellId) if (spellInfo->Dispel == DISPEL_CURSE) return SPELL_CURSE; - // family flag 37 (only part spells have family name) - if (spellInfo->SpellFamilyFlags & 0x2000000000LL) + // Warlock (Demon Armor | Demon Skin | Fel Armor) + if (spellInfo->SpellFamilyFlags[1] & 0x20000020 || spellInfo->SpellFamilyFlags[2] & 0x00000010) return SPELL_WARLOCK_ARMOR; //seed of corruption and corruption - if (spellInfo->SpellFamilyFlags & 0x1000000002LL) + if (spellInfo->SpellFamilyFlags[1] & 0x10 || spellInfo->SpellFamilyFlags[0] & 0x2) return SPELL_WARLOCK_CORRUPTION; break; } @@ -364,6 +353,13 @@ SpellSpecific GetSpellSpecific(uint32 spellId) if (spellInfo->Dispel == DISPEL_POISON) return SPELL_STING; + // only hunter aspects have this + if( spellInfo->SpellFamilyFlags[1] & 0x00440000 || spellInfo->SpellFamilyFlags[0] & 0x00380000 || spellInfo->SpellFamilyFlags[2] & 0x00003010) + return SPELL_ASPECT; + + if( spellInfo->SpellFamilyFlags[2] & 0x00000002 ) + return SPELL_TRACKER; + break; } case SPELLFAMILY_PALADIN: @@ -371,16 +367,16 @@ SpellSpecific GetSpellSpecific(uint32 spellId) if (IsSealSpell(spellInfo)) return SPELL_SEAL; - if (spellInfo->SpellFamilyFlags & 0x10000100LL) + if (spellInfo->SpellFamilyFlags[0] & 0x11010002) return SPELL_BLESSING; - if ((spellInfo->SpellFamilyFlags & 0x00000820180400LL) && (spellInfo->AttributesEx3 & 0x200)) + if ((spellInfo->SpellFamilyFlags[1] & 0x000008 || spellInfo->SpellFamilyFlags[0] & 20180400) && (spellInfo->AttributesEx3 & 0x200)) return SPELL_JUDGEMENT; for (int i = 0; i < 3; i++) { - // only paladin auras have this - if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY) + // only paladin auras have this (for palaldin class family) + if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID) return SPELL_AURA; } break; @@ -395,28 +391,13 @@ SpellSpecific GetSpellSpecific(uint32 spellId) case SPELLFAMILY_POTION: return spellmgr.GetSpellElixirSpecific(spellInfo->Id); - } - // only warlock armor/skin have this (in additional to family cases) - if( spellInfo->SpellVisual == 130 && spellInfo->SpellIconID == 89) - { - return SPELL_WARLOCK_ARMOR; - } - - // only hunter aspects have this (but not all aspects in hunter family) - if( spellInfo->activeIconID == 122 && (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_NATURE) && - (spellInfo->Attributes & 0x50000) != 0 && (spellInfo->Attributes & 0x9000010) == 0) - { - return SPELL_ASPECT; + case SPELLFAMILY_DEATHKNIGHT: + if ((spellInfo->Attributes & 0x10) && (spellInfo->AttributesEx2 & 0x10) && (spellInfo->AttributesEx4 & 0x200000)) + return SPELL_PRESENCE; + break; } - for(int i = 0; i < 3; i++) - if( spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA && ( - spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_CREATURES || - spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_RESOURCES || - spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_STEALTHED ) ) - return SPELL_TRACKER; - // elixirs can have different families, but potion most ofc. if(SpellSpecific sp = spellmgr.GetSpellElixirSpecific(spellInfo->Id)) return sp; @@ -452,6 +433,7 @@ bool IsSingleFromSpellSpecificPerTarget(uint32 spellSpec1,uint32 spellSpec2) case SPELL_MAGE_ARMOR: case SPELL_ELEMENTAL_SHIELD: case SPELL_MAGE_POLYMORPH: + case SPELL_PRESENCE: case SPELL_WELL_FED: case SPELL_DRINK: case SPELL_FOOD: @@ -484,8 +466,6 @@ bool IsPositiveTarget(uint32 targetA, uint32 targetB) case TARGET_CURRENT_ENEMY_COORDINATES: case TARGET_UNIT_CHANNEL: return false; - case TARGET_ALL_AROUND_CASTER: - return (targetB == TARGET_ALL_PARTY || targetB == TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER); default: break; } @@ -891,8 +871,8 @@ void SpellMgr::LoadSpellAffects() uint32 count = 0; - // 0 1 2 - QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellFamilyMask FROM spell_affect"); + // 0 1 2 3 4 + QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellClassMask0, SpellClassMask1, SpellClassMask2 FROM spell_affect"); if( !result ) { @@ -939,26 +919,22 @@ void SpellMgr::LoadSpellAffects() continue; } - uint64 spellAffectMask = fields[2].GetUInt64(); + flag96 affect(fields[2].GetUInt32(), fields[3].GetUInt32(), fields[4].GetUInt32()); - // Spell.dbc have own data for low part of SpellFamilyMask - if( spellInfo->EffectItemType[effectId]) - { - if(spellInfo->EffectItemType[effectId] == spellAffectMask) - { - sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectItemType%d) data for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId); - continue; - } + // Spell.dbc have own data + if (effectId>3) + continue; - // 24429 have wrong data in EffectItemType and overwrites by DB, possible bug in client - if(spellInfo->Id!=24429 && spellInfo->EffectItemType[effectId] != spellAffectMask) - { - sLog.outErrorDb("Spell %u listed in `spell_affect` have different low part from EffectItemType%d for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId); - continue; - } + flag96 dbc_affect; + dbc_affect = spellInfo->EffectSpellClassMask[effectId]; + if(dbc_affect[0] == affect[0] || dbc_affect[1] == affect[1] || dbc_affect[2] == affect[2]) + { + char text[]="ABC"; + sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectSpellClassMask%c) data for effect index (%u) and not needed, skipped.", entry, text[effectId], effectId); + continue; } - mSpellAffectMap.insert(SpellAffectMap::value_type((entry<<8) + effectId,spellAffectMask)); + mSpellAffectMap[(entry<<8) + effectId] = affect; ++count; } while( result->NextRow() ); @@ -966,7 +942,7 @@ void SpellMgr::LoadSpellAffects() delete result; sLog.outString(); - sLog.outString( ">> Loaded %u spell affect definitions", count ); + sLog.outString( ">> Loaded %u custom spell affect definitions", count ); for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id) { @@ -982,7 +958,9 @@ void SpellMgr::LoadSpellAffects() spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER) ) continue; - if(spellInfo->EffectItemType[effectId] != 0) + flag96 dbc_affect; + dbc_affect = spellInfo->EffectSpellClassMask[effectId]; + if(dbc_affect) continue; if(mSpellAffectMap.find((id<<8) + effectId) != mSpellAffectMap.end()) @@ -993,33 +971,19 @@ void SpellMgr::LoadSpellAffects() } } -bool SpellMgr::IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const +bool SpellMgr::IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const { // false for spellInfo == NULL - if (!spellInfo) + if (!spellInfo || !mod) return false; - SpellEntry const *affect_spell = sSpellStore.LookupEntry(spellId); - // false for affect_spell == NULL - if (!affect_spell) + SpellEntry const *affect_spell = sSpellStore.LookupEntry(mod->spellId); + // False if affect_spell == NULL or spellFamily not equal + if (!affect_spell || affect_spell->SpellFamilyName != spellInfo->SpellFamilyName) return false; - // False if spellFamily not equal - if (affect_spell->SpellFamilyName != spellInfo->SpellFamilyName) - return false; - - // If familyFlags == 0 - if (!familyFlags) - { - // Get it from spellAffect table - familyFlags = GetSpellAffectMask(spellId,effectId); - // false if familyFlags == 0 - if (!familyFlags) - return false; - } - // true - if (familyFlags & spellInfo->SpellFamilyFlags) + if (mod->mask & spellInfo->SpellFamilyFlags) return true; return false; @@ -1031,15 +995,12 @@ void SpellMgr::LoadSpellProcEvents() uint32 count = 0; - // 0 1 2 3 4 5 6 7 8 - QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMask, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event"); + // 0 1 2 3 4 5 6 7 8 9 10 + QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMask0, SpellFamilyMask1, SpellFamilyMask2, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event"); if( !result ) { - barGoLink bar( 1 ); - bar.step(); - sLog.outString(); sLog.outString( ">> Loaded %u spell proc event conditions", count ); return; @@ -1053,7 +1014,7 @@ void SpellMgr::LoadSpellProcEvents() bar.step(); - uint16 entry = fields[0].GetUInt16(); + uint32 entry = fields[0].GetUInt32(); const SpellEntry *spell = sSpellStore.LookupEntry(entry); if (!spell) @@ -1066,12 +1027,13 @@ void SpellMgr::LoadSpellProcEvents() spe.schoolMask = fields[1].GetUInt32(); spe.spellFamilyName = fields[2].GetUInt32(); - spe.spellFamilyMask = fields[3].GetUInt64(); - spe.procFlags = fields[4].GetUInt32(); - spe.procEx = fields[5].GetUInt32(); - spe.ppmRate = fields[6].GetFloat(); - spe.customChance = fields[7].GetFloat(); - spe.cooldown = fields[8].GetUInt32(); + spe.spellFamilyMask = (uint64)fields[3].GetUInt32()|((uint64)fields[4].GetUInt32()<<32); + spe.spellFamilyMask2= fields[5].GetUInt32(); + spe.procFlags = fields[6].GetUInt32(); + spe.procEx = fields[7].GetUInt32(); + spe.ppmRate = fields[8].GetFloat(); + spe.customChance = fields[9].GetFloat(); + spe.cooldown = fields[10].GetUInt32(); mSpellProcEventMap[entry] = spe; @@ -1091,80 +1053,54 @@ void SpellMgr::LoadSpellProcEvents() sLog.outString(); if (customProc) - sLog.outString( ">> Loaded %u custom spell proc event conditions +%u custom", count, customProc ); + sLog.outString( ">> Loaded %u extra spell proc event conditions +%u custom", count, customProc ); else - sLog.outString( ">> Loaded %u spell proc event conditions", count ); + sLog.outString( ">> Loaded %u extra spell proc event conditions", count ); +} - /* - // Commented for now, as it still produces many errors (still quite many spells miss spell_proc_event) - for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id) +void SpellMgr::LoadSpellBonusess() +{ + mSpellBonusMap.clear(); // need for reload case + uint32 count = 0; + // 0 1 2 3 + QueryResult *result = WorldDatabase.Query("SELECT entry, direct_bonus, dot_bonus, ap_bonus FROM spell_bonus_data"); + if( !result ) { - SpellEntry const* spellInfo = sSpellStore.LookupEntry(id); - if (!spellInfo) - continue; - - bool found = false; - for (int effectId = 0; effectId < 3; ++effectId) - { - // at this moment check only SPELL_AURA_PROC_TRIGGER_SPELL - if( spellInfo->EffectApplyAuraName[effectId] == SPELL_AURA_PROC_TRIGGER_SPELL ) - { - found = true; - break; - } - } + barGoLink bar( 1 ); + bar.step(); + sLog.outString(); + sLog.outString( ">> Loaded %u spell bonus data", count); + return; + } - if(!found) - continue; + barGoLink bar( result->GetRowCount() ); + do + { + Field *fields = result->Fetch(); + bar.step(); + uint32 entry = fields[0].GetUInt32(); - if(GetSpellProcEvent(id)) + const SpellEntry *spell = sSpellStore.LookupEntry(entry); + if (!spell) + { + sLog.outErrorDb("Spell %u listed in `spell_bonus_data` does not exist", entry); continue; + } - sLog.outErrorDb("Spell %u (%s) misses spell_proc_event",id,spellInfo->SpellName[sWorld.GetDBClang()]); - } - */ -} - -/* -bool SpellMgr::IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, SpellEntry const * procSpell, uint32 procFlags ) -{ - if((procFlags & spellProcEvent->procFlags) == 0) - return false; + SpellBonusEntry sbe; - // Additional checks in case spell cast/hit/crit is the event - // Check (if set) school, category, skill line, spell talent mask - if(spellProcEvent->schoolMask && (!procSpell || (GetSpellSchoolMask(procSpell) & spellProcEvent->schoolMask) == 0)) - return false; - if(spellProcEvent->category && (!procSpell || procSpell->Category != spellProcEvent->category)) - return false; - if(spellProcEvent->skillId) - { - if (!procSpell) - return false; + sbe.direct_damage = fields[1].GetFloat(); + sbe.dot_damage = fields[2].GetFloat(); + sbe.ap_bonus = fields[3].GetFloat(); - SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(procSpell->Id); - SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(procSpell->Id); + mSpellBonusMap[entry] = sbe; + } while( result->NextRow() ); - bool found = false; - for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) - { - if(_spell_idx->second->skillId == spellProcEvent->skillId) - { - found = true; - break; - } - } - if (!found) - return false; - } - if(spellProcEvent->spellFamilyName && (!procSpell || spellProcEvent->spellFamilyName != procSpell->SpellFamilyName)) - return false; - if(spellProcEvent->spellFamilyMask && (!procSpell || (spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags) == 0)) - return false; + delete result; - return true; + sLog.outString(); + sLog.outString( ">> Loaded %u extra spell bonus data", count); } -*/ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active) { @@ -1176,7 +1112,7 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellP return false; // Always trigger for this - if (EventProcFlag & (PROC_FLAG_KILLED | PROC_FLAG_KILL_AND_GET_XP)) + if (EventProcFlag & (PROC_FLAG_KILLED | PROC_FLAG_KILL | PROC_FLAG_ON_TRAP_ACTIVATION)) return true; if (spellProcEvent) // Exist event data @@ -1202,9 +1138,9 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellP return false; // spellFamilyName is Ok need check for spellFamilyMask if present - if(spellProcEvent->spellFamilyMask) + if(spellProcEvent->spellFamilyMask || spellProcEvent->spellFamilyMask2) { - if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags) == 0) + if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags ) == 0) return false; active = true; // Spell added manualy -> so its active spell } @@ -1303,28 +1239,38 @@ bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellI bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo) { + if(IsPassiveSpell(spellInfo->Id)) // ranked passive spell + return false; if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH) return false; - if(IsProfessionSpell(spellInfo->Id)) + if(IsProfessionOrRidingSpell(spellInfo->Id)) + return false; + + if(spellmgr.IsSkillBonusSpell(spellInfo->Id)) return false; // All stance spells. if any better way, change it. for (int i = 0; i < 3; i++) { - // Paladin aura Spell - if(spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN - && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY) - return false; - // Druid form Spell - if(spellInfo->SpellFamilyName == SPELLFAMILY_DRUID - && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA - && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT) - return false; - // Rogue Stealth - if(spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE - && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA - && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT) - return false; + switch(spellInfo->SpellFamilyName) + { + case SPELLFAMILY_PALADIN: + // Paladin aura Spell + if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_RAID) + return false; + break; + case SPELLFAMILY_DRUID: + // Druid form Spell + if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA && + spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT) + return false; + break; + case SPELLFAMILY_ROGUE: + // Rogue Stealth + if (spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA && + spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT) + return false; + } } return true; } @@ -1353,6 +1299,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool if(spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName) return false; + // TODO: Is this needed? + // Allow stack passive and not passive spells + if ((spellInfo_1->Attributes & SPELL_ATTR_PASSIVE)!=(spellInfo_2->Attributes & SPELL_ATTR_PASSIVE)) + return false; + // generic spells if(!spellInfo_1->SpellFamilyName) { @@ -1407,6 +1358,21 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool return true; } + +bool SpellMgr::IsProfessionOrRidingSpell(uint32 spellId) +{ + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if(!spellInfo) + return false; + + if(spellInfo->Effect[1] != SPELL_EFFECT_SKILL) + return false; + + uint32 skill = spellInfo->EffectMiscValue[1]; + + return IsProfessionOrRidingSkill(skill); +} + bool SpellMgr::IsProfessionSpell(uint32 spellId) { SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); @@ -1440,6 +1406,24 @@ bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId) const return IsPrimaryProfessionSpell(spellId) && GetSpellRank(spellId)==1; } +bool SpellMgr::IsSkillBonusSpell(uint32 spellId) const +{ + SkillLineAbilityMap::const_iterator lower = GetBeginSkillLineAbilityMap(spellId); + SkillLineAbilityMap::const_iterator upper = GetEndSkillLineAbilityMap(spellId); + + for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx) + { + SkillLineAbilityEntry const *pAbility = _spell_idx->second; + if (!pAbility || pAbility->learnOnGetSkill != ABILITY_LEARNED_ON_GET_PROFESSION_SKILL) + continue; + + if(pAbility->req_skill_value > 0) + return true; + } + + return false; +} + SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const { // ignore passive spells @@ -1451,7 +1435,8 @@ SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spell { if( IsPositiveEffect(spellInfo->Id, i) && ( spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA || - spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY + spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID ) ) { needRankSelection = true; @@ -1526,21 +1511,31 @@ struct SpellRankEntry uint32 RangeIndex; uint32 SpellVisual; uint32 ProcFlags; - uint64 SpellFamilyFlags; + flag96 SpellFamilyFlags; uint32 TargetAuraState; uint32 ManaCost; - - bool operator()(const SpellRankEntry & _Left,const SpellRankEntry & _Right)const - { - return (_Left.SkillId != _Right.SkillId ? _Left.SkillId < _Right.SkillId - : _Left.SpellName!=_Right.SpellName ? _Left.SpellName < _Right.SpellName - : _Left.ProcFlags!=_Right.ProcFlags ? _Left.ProcFlags < _Right.ProcFlags - : _Left.SpellFamilyFlags!=_Right.SpellFamilyFlags ? _Left.SpellFamilyFlags < _Right.SpellFamilyFlags - : (_Left.SpellVisual!=_Right.SpellVisual) && (!_Left.SpellVisual || !_Right.SpellVisual) ? _Left.SpellVisual < _Right.SpellVisual - : (_Left.ManaCost!=_Right.ManaCost) && (!_Left.ManaCost || !_Right.ManaCost) ? _Left.ManaCost < _Right.ManaCost - : (_Left.DurationIndex!=_Right.DurationIndex) && (!_Left.DurationIndex || !_Right.DurationIndex)? _Left.DurationIndex < _Right.DurationIndex - : (_Left.RangeIndex!=_Right.RangeIndex) && (!_Left.RangeIndex || !_Right.RangeIndex || _Left.RangeIndex==1 || !_Right.RangeIndex==1) ? _Left.RangeIndex < _Right.RangeIndex - : _Left.TargetAuraState < _Right.TargetAuraState + uint32 CastingTimeIndex; + flag96 Effect; + flag96 Aura; + uint16 TalentID; + + bool operator < (const SpellRankEntry & _Right) const + { + return (SkillId != _Right.SkillId ? SkillId < _Right.SkillId + : SpellName!=_Right.SpellName ? SpellName < _Right.SpellName + : ProcFlags!=_Right.ProcFlags ? ProcFlags < _Right.ProcFlags + + : Effect!=_Right.Effect ? Effect < _Right.Effect + : Aura!=_Right.Aura ? Aura < _Right.Aura + : TalentID!=_Right.TalentID ? TalentID < _Right.TalentID + : (CastingTimeIndex!=_Right.CastingTimeIndex) && (!CastingTimeIndex || !_Right.CastingTimeIndex || CastingTimeIndex==1 || !_Right.CastingTimeIndex==1) ? CastingTimeIndex < _Right.CastingTimeIndex + + : SpellFamilyFlags!=_Right.SpellFamilyFlags ? SpellFamilyFlags < _Right.SpellFamilyFlags + : (SpellVisual!=_Right.SpellVisual) && (!SpellVisual || !_Right.SpellVisual) ? SpellVisual < _Right.SpellVisual + : (ManaCost!=_Right.ManaCost) && (!ManaCost || !_Right.ManaCost) ? ManaCost < _Right.ManaCost + : (DurationIndex!=_Right.DurationIndex) && (!DurationIndex || !_Right.DurationIndex)? DurationIndex < _Right.DurationIndex + : (RangeIndex!=_Right.RangeIndex) && (!RangeIndex || !_Right.RangeIndex || RangeIndex==1 || !_Right.RangeIndex==1) ? RangeIndex < _Right.RangeIndex + : TargetAuraState < _Right.TargetAuraState ); } }; @@ -1549,6 +1544,7 @@ struct SpellRankValue { uint32 Id; char const *Rank; + bool strict; }; void SpellMgr::LoadSpellChains() @@ -1561,14 +1557,12 @@ void SpellMgr::LoadSpellChains() SkillLineAbilityEntry const *AbilityInfo=sSkillLineAbilityStore.LookupEntry(ability_id); if (!AbilityInfo) continue; - if (AbilityInfo->spellId==20154) //exception to these rules (not needed in 3.0.3) - continue; if (!AbilityInfo->forward_spellid) continue; ChainedSpells.push_back(AbilityInfo->forward_spellid); } - std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry> RankMap; + std::multimap<SpellRankEntry, SpellRankValue> RankMap; for (uint32 ability_id=0;ability_id<sSkillLineAbilityStore.GetNumRows();ability_id++) { @@ -1578,8 +1572,6 @@ void SpellMgr::LoadSpellChains() //get only spell with lowest ability_id to prevent doubles uint32 spell_id=AbilityInfo->spellId; - if (spell_id==20154) //exception to these rules (not needed in 3.0.3) - continue; bool found=false; for (uint32 i=0; i<ChainedSpells.size(); i++) { @@ -1598,7 +1590,7 @@ void SpellMgr::LoadSpellChains() if(sRank.empty()) continue; //exception to polymorph spells-make pig and turtle other chain than sheep - if ((SpellInfo->SpellFamilyName==SPELLFAMILY_MAGE) && (SpellInfo->SpellFamilyFlags & 0x1000000) && (SpellInfo->SpellIconID!=82)) + if ((SpellInfo->SpellFamilyName==SPELLFAMILY_MAGE) && (SpellInfo->SpellFamilyFlags[0] & 0x1000000) && (SpellInfo->SpellIconID!=82)) continue; SpellRankEntry entry; @@ -1610,14 +1602,16 @@ void SpellMgr::LoadSpellChains() entry.ProcFlags=SpellInfo->procFlags; entry.SpellFamilyFlags=SpellInfo->SpellFamilyFlags; entry.TargetAuraState=SpellInfo->TargetAuraState; - entry.SpellVisual=SpellInfo->SpellVisual; + entry.SpellVisual=SpellInfo->SpellVisual[0]; entry.ManaCost=SpellInfo->manaCost; - + entry.CastingTimeIndex=0; + entry.TalentID=0; for (;;) { AbilityInfo=mSkillLineAbilityMap.lower_bound(spell_id)->second; value.Id=spell_id; value.Rank=SpellInfo->Rank[sWorld.GetDefaultDbcLocale()]; + value.strict=false; RankMap.insert(std::pair<SpellRankEntry, SpellRankValue>(entry,value)); spell_id=AbilityInfo->forward_spellid; SpellInfo=sSpellStore.LookupEntry(spell_id); @@ -1630,48 +1624,109 @@ void SpellMgr::LoadSpellChains() uint32 count=0; - for (std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator itr = RankMap.begin();itr!=RankMap.end();) + for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr = RankMap.begin();itr!=RankMap.end();) { SpellRankEntry entry=itr->first; //trac errors in extracted data - std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator> RankErrorMap; - for (std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2++) + std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator> RankErrorMap; + for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2++) { bar.step(); - RankErrorMap.insert(std::pair<char const *, std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator>(itr2->second.Rank,itr2)); - } - for (std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator>::iterator itr2 = RankErrorMap.begin();itr2!=RankErrorMap.end();) - { - char const * err_entry=itr2->first; - uint32 rank_count=RankErrorMap.count(itr2->first); - if (rank_count>1) - for (itr2 = RankErrorMap.lower_bound(err_entry);itr2!=RankErrorMap.upper_bound(err_entry);itr2++) + RankErrorMap.insert(std::pair<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator>(itr2->second.Rank,itr2)); + } + + bool error=false; + //if strict == true strict check is not needed + if (!itr->second.strict) + //check for rank duplicates, if there are any do strict check + for (std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator>::iterator itr2 = RankErrorMap.begin();itr2!=RankErrorMap.end();) { - sLog.outDebug("There is a duplicate rank entry (%s) for spell: %u",itr2->first,itr2->second->second.Id); - sLog.outDebug("Spell %u removed from chain data.",itr2->second->second.Id); - RankMap.erase(itr2->second); - itr=RankMap.lower_bound(entry); + char const * err_entry=itr2->first; + uint32 rank_count=RankErrorMap.count(itr2->first); + if (rank_count>1) + { + error=true; + break; + } + else + itr2++; } - else - itr2++; - } - //do not proceed for spells with less than 2 ranks - uint32 spell_max_rank=RankMap.count(entry); - if (spell_max_rank<2) + bool allHaveTalents=true; + if (error) { - itr=RankMap.upper_bound(entry); + std::list<uint32> ConflictedSpells; + for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2=RankMap.lower_bound(entry)) + { + ConflictedSpells.push_back(itr2->second.Id); + if (!GetTalentSpellPos(itr2->second.Id)) + allHaveTalents=false; + RankMap.erase(itr2); + } + SpellRankEntry nextEntry, currEntry; + for (;!ConflictedSpells.empty();ConflictedSpells.pop_front()) + { + SpellEntry const *SpellInfo=sSpellStore.LookupEntry(ConflictedSpells.front()); + currEntry.SkillId=entry.SkillId; + currEntry.SpellName=SpellInfo->SpellName[sWorld.GetDefaultDbcLocale()]; + currEntry.DurationIndex=SpellInfo->DurationIndex; + currEntry.RangeIndex=SpellInfo->rangeIndex; + currEntry.ProcFlags=SpellInfo->procFlags; + currEntry.SpellFamilyFlags=SpellInfo->SpellFamilyFlags; + //compare talents only when all spells from chain have entry + //to prevent wrong results with spells which have first rank talented and other not + if (allHaveTalents) + currEntry.TalentID=GetTalentSpellPos(ConflictedSpells.front())->talent_id; + else + currEntry.TalentID=0; + currEntry.TargetAuraState=SpellInfo->TargetAuraState; + currEntry.SpellVisual=SpellInfo->SpellVisual[0]; + currEntry.ManaCost=SpellInfo->manaCost; + + //compare effects and casting time + currEntry.CastingTimeIndex=SpellInfo->CastingTimeIndex; + currEntry.Effect[0]=SpellInfo->Effect[0]; + currEntry.Effect[1]=SpellInfo->Effect[1]; + currEntry.Effect[2]=SpellInfo->Effect[2]; + + currEntry.Aura[0]=SpellInfo->EffectApplyAuraName[0]; + currEntry.Aura[1]=SpellInfo->EffectApplyAuraName[1]; + currEntry.Aura[2]=SpellInfo->EffectApplyAuraName[2]; + + SpellRankValue currValue; + currValue.Id=ConflictedSpells.front(); + currValue.Rank=SpellInfo->Rank[sWorld.GetDefaultDbcLocale()]; + currValue.strict=true; + RankMap.insert(std::pair<SpellRankEntry, SpellRankValue>(currEntry,currValue)); + } + itr=RankMap.begin(); continue; } + else + for (std::multimap<char const *, std::multimap<SpellRankEntry, SpellRankValue>::iterator>::iterator itr2 = RankErrorMap.begin();itr2!=RankErrorMap.end();) + { + char const * err_entry=itr2->first; + uint32 rank_count=RankErrorMap.count(itr2->first); + if (rank_count>1) + for (itr2 = RankErrorMap.lower_bound(err_entry);itr2!=RankErrorMap.upper_bound(err_entry);itr2++) + { + sLog.outDebug("There is a duplicate rank entry (%s) for spell: %u",itr2->first,itr2->second->second.Id); + if (!(itr2->second->second.Id==52375 || itr2->second->second.Id==45902)) + { + sLog.outDebug("Spell %u removed from chain data.",itr2->second->second.Id); + RankMap.erase(itr2->second); + } + } + else + itr2++; + } - itr=RankMap.upper_bound(entry); - - //order spells by spells by spellLevel + //order spells by spellLevel std::list<uint32> RankedSpells; uint32 min_spell_lvl=0; - std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator min_itr; + std::multimap<SpellRankEntry, SpellRankValue>::iterator min_itr; for (;RankMap.count(entry);) { - for (std::multimap<SpellRankEntry, SpellRankValue,SpellRankEntry>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2++) + for (std::multimap<SpellRankEntry, SpellRankValue>::iterator itr2 = RankMap.lower_bound(entry);itr2!=RankMap.upper_bound(entry);itr2++) { SpellEntry const *SpellInfo=sSpellStore.LookupEntry(itr2->second.Id); if (SpellInfo->spellLevel<min_spell_lvl || itr2==RankMap.lower_bound(entry)) @@ -1707,9 +1762,13 @@ void SpellMgr::LoadSpellChains() } } + //do not proceed for spells with less than 2 ranks + itr=RankMap.begin(); + if (RankedSpells.size()<2) + continue; + count++; - itr=RankMap.upper_bound(entry); uint32 spell_rank=1; for(std::list<uint32>::iterator itr2 = RankedSpells.begin();itr2!=RankedSpells.end();spell_rank++) { @@ -1733,8 +1792,8 @@ void SpellMgr::LoadSpellChains() } //uncomment these two lines to print yourself list of spell_chains on startup -// for (UNORDERED_MAP<uint32, SpellChainNode>::iterator itr=mSpellChains.begin();itr!=mSpellChains.end();itr++) -// sLog.outString( "Id: %u, Rank: %d , %s",itr->first,itr->second.rank, sSpellStore.LookupEntry(itr->first)->Rank[sWorld.GetDefaultDbcLocale()]); + //for (UNORDERED_MAP<uint32, SpellChainNode>::iterator itr=mSpellChains.begin();itr!=mSpellChains.end();itr++) + //sLog.outString( "Id: %u, Rank: %d , %s, %u, %u, %u, %u",itr->first,itr->second.rank, sSpellStore.LookupEntry(itr->first)->Rank[sWorld.GetDefaultDbcLocale()], itr->second.first, itr->second.last,itr->second.next ,itr->second.prev); sLog.outString(); sLog.outString( ">> Loaded %u spell chains",count); @@ -1746,8 +1805,10 @@ void SpellMgr::LoadSpellLearnSkills() // search auto-learned skills and add its to map also for use in unlearn spells/talents uint32 dbc_count = 0; + barGoLink bar( sSpellStore.GetNumRows() ); for(uint32 spell = 0; spell < sSpellStore.GetNumRows(); ++spell) { + bar.step(); SpellEntry const* entry = sSpellStore.LookupEntry(spell); if(!entry) @@ -1782,7 +1843,8 @@ void SpellMgr::LoadSpellLearnSpells() { mSpellLearnSpells.clear(); // need for reload case - QueryResult *result = WorldDatabase.Query("SELECT entry, SpellID FROM spell_learn_spell"); + // 0 1 2 + QueryResult *result = WorldDatabase.Query("SELECT entry, SpellID, Active FROM spell_learn_spell"); if(!result) { barGoLink bar( 1 ); @@ -1806,6 +1868,7 @@ void SpellMgr::LoadSpellLearnSpells() SpellLearnSpellNode node; node.spell = fields[1].GetUInt32(); + node.active = fields[2].GetBool(); node.autoLearned= false; if(!sSpellStore.LookupEntry(spell_id)) @@ -1842,7 +1905,16 @@ void SpellMgr::LoadSpellLearnSpells() { SpellLearnSpellNode dbc_node; dbc_node.spell = entry->EffectTriggerSpell[i]; - dbc_node.autoLearned = true; + dbc_node.active = true; // all dbc based learned spells is active (show in spell book or hide by client itself) + + // ignore learning not existed spells (broken/outdated/or generic learnig spell 483 + if(!sSpellStore.LookupEntry(dbc_node.spell)) + continue; + + // talent or passive spells or skill-step spells auto-casted and not need dependent learning, + // pet teaching spells don't must be dependent learning (casted) + // other required explicit dependent learning + dbc_node.autoLearned = entry->EffectImplicitTargetA[i]==TARGET_PET || GetTalentSpellCost(spell) > 0 || IsPassiveSpell(spell) || IsSpellHaveEffect(entry,SPELL_EFFECT_SKILL_STEP); SpellLearnSpellMap::const_iterator db_node_begin = GetBeginSpellLearnSpell(spell); SpellLearnSpellMap::const_iterator db_node_end = GetEndSpellLearnSpell(spell); @@ -2161,7 +2233,7 @@ void SpellMgr::LoadSpellCustomAttr() } } - if(spellInfo->SpellVisual == 3879) + if(spellInfo->SpellVisual[0] == 3879) mSpellCustomAttr[i] |= SPELL_ATTR_CU_CONE_BACK; switch(i) @@ -2303,6 +2375,187 @@ void SpellMgr::LoadSpellLinked() } /// Some checks for spells, to prevent adding depricated/broken spells for trainers, spell book, etc +void SpellMgr::LoadPetLevelupSpellMap() +{ + CreatureFamilyEntry const *creatureFamily; + SpellEntry const *spell; + uint32 count = 0; + + for (uint32 i = 0; i < sCreatureFamilyStore.GetNumRows(); ++i) + { + creatureFamily = sCreatureFamilyStore.LookupEntry(i); + + if(!creatureFamily) // not exist + continue; + + if(creatureFamily->petTalentType < 0) // not hunter pet family + continue; + + for(uint32 j = 0; j < sSpellStore.GetNumRows(); ++j) + { + spell = sSpellStore.LookupEntry(j); + + // not exist + if(!spell) + continue; + + // not hunter spell + if(spell->SpellFamilyName != SPELLFAMILY_HUNTER) + continue; + + // not pet spell + if(!(spell->SpellFamilyFlags[1] & 0x10000000)) + continue; + + // not Growl or Cower (generics) + if(spell->SpellIconID != 201 && spell->SpellIconID != 958) + { + switch(creatureFamily->ID) + { + case CREATURE_FAMILY_BAT: // Bite and Sonic Blast + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1577) + continue; + break; + case CREATURE_FAMILY_BEAR: // Claw and Swipe + if(spell->SpellIconID != 262 && spell->SpellIconID != 1562) + continue; + break; + case CREATURE_FAMILY_BIRD_OF_PREY: // Claw and Snatch + if(spell->SpellIconID != 262 && spell->SpellIconID != 168) + continue; + break; + case CREATURE_FAMILY_BOAR: // Bite and Gore + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1578) + continue; + break; + case CREATURE_FAMILY_CARRION_BIRD: // Bite and Demoralizing Screech + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1579) + continue; + break; + case CREATURE_FAMILY_CAT: // Claw and Prowl and Rake + if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 494) + continue; + break; + case CREATURE_FAMILY_CHIMAERA: // Bite and Froststorm Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) + continue; + break; + case CREATURE_FAMILY_CORE_HOUND: // Bite and Lava Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1197) + continue; + break; + case CREATURE_FAMILY_CRAB: // Claw and Pin + if(spell->SpellIconID != 262 && spell->SpellIconID != 2679) + continue; + break; + case CREATURE_FAMILY_CROCOLISK: // Bite and Bad Attitude + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1581) + continue; + break; + case CREATURE_FAMILY_DEVILSAUR: // Bite and Monstrous Bite + if(spell->SpellIconID != 1680 && spell->SpellIconID != 599) + continue; + break; + case CREATURE_FAMILY_DRAGONHAWK: // Bite and Fire Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2128) + continue; + break; + case CREATURE_FAMILY_GORILLA: // Smack and Thunderstomp + if(spell->SpellIconID != 473 && spell->SpellIconID != 148) + continue; + break; + case CREATURE_FAMILY_HYENA: // Bite and Tendon Rip + if(spell->SpellIconID != 1680 && spell->SpellIconID != 138) + continue; + break; + case CREATURE_FAMILY_MOTH: // Serenity Dust and Smack + if(spell->SpellIconID != 1714 && spell->SpellIconID != 473) + continue; + break; + case CREATURE_FAMILY_NETHER_RAY: // Bite and Nether Shock + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2027) + continue; + break; + case CREATURE_FAMILY_RAPTOR: // Claw and Savage Rend + if(spell->SpellIconID != 262 && spell->SpellIconID != 245) + continue; + break; + case CREATURE_FAMILY_RAVAGER: // Bite and Ravage + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2253) + continue; + break; + case CREATURE_FAMILY_RHINO: // Smack and Stampede + if(spell->SpellIconID != 473 && spell->SpellIconID != 3066) + continue; + break; + case CREATURE_FAMILY_SCORPID: // Claw and Scorpid Poison + if(spell->SpellIconID != 262 && spell->SpellIconID != 163) + continue; + break; + case CREATURE_FAMILY_SERPENT: // Bite and Poison Spit + if(spell->SpellIconID != 1680 && spell->SpellIconID != 68) + continue; + break; + case CREATURE_FAMILY_SILITHID: // Claw and Venom Web Spray + if(spell->SpellIconID != 262 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 12013)) + continue; + break; + case CREATURE_FAMILY_SPIDER: // Bite and Web + if(spell->SpellIconID != 1680 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 684)) + continue; + break; + case CREATURE_FAMILY_SPIRIT_BEAST: // Claw and Prowl and Spirit Strike + if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 255) + continue; + break; + case CREATURE_FAMILY_SPOREBAT: // Smack and Spore Cloud + if(spell->SpellIconID != 473 && spell->SpellIconID != 2681) + continue; + break; + case CREATURE_FAMILY_TALLSTRIDER: // Claw and Dust Cloud + if(spell->SpellIconID != 262 && (spell->SpellIconID != 157 && !(spell->Attributes & 0x4000000))) + continue; + break; + case CREATURE_FAMILY_TURTLE: // Bite and Shell Shield + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1588) + continue; + break; + case CREATURE_FAMILY_WARP_STALKER: // Bite and Warp + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1952) + continue; + break; + case CREATURE_FAMILY_WASP: // Smack and Sting + if(spell->SpellIconID != 473 && spell->SpellIconID != 110) + continue; + break; + case CREATURE_FAMILY_WIND_SERPENT: // Bite and Lightning Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) + continue; + break; + case CREATURE_FAMILY_WOLF: // Bite and Furious Howl + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1573) + continue; + break; + case CREATURE_FAMILY_WORM: // Acid Spit and Bite + if(spell->SpellIconID != 636 && spell->SpellIconID != 1680) + continue; + break; + default: + sLog.outError("LoadPetLevelupSpellMap: Unhandled creature family %u", creatureFamily->ID); + continue; + } + } + + mPetLevelupSpellMap[creatureFamily->ID][spell->spellLevel] = spell->Id; + count++; + } + } + + sLog.outString(); + sLog.outString( ">> Loaded %u pet levelup spells", count ); +} + +/// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg) { // not exist @@ -2377,11 +2630,24 @@ bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg) return true; } -bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id) +uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id, uint32 bgInstanceId) { // normal case - if( spellInfo->AreaId && spellInfo->AreaId != zone_id && spellInfo->AreaId != area_id ) - return false; + if( spellInfo->AreaGroupId > 0) + { + bool found = false; + + AreaGroupEntry const* groupEntry = sAreaGroupStore.LookupEntry(spellInfo->AreaGroupId); + if(groupEntry) + { + for (uint8 i=0; i<7; i++) + if( groupEntry->AreaId[i] == zone_id || groupEntry->AreaId[i] == area_id ) + found = true; + } + + if(!found) + return SPELL_FAILED_INCORRECT_AREA; + } // elixirs (all area dependent elixirs have family SPELLFAMILY_POTION, use this for speedup) if(spellInfo->SpellFamilyName==SPELLFAMILY_POTION) @@ -2391,28 +2657,28 @@ bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 z if(mask & ELIXIR_BATTLE_MASK) { if(spellInfo->Id==45373) // Bloodberry Elixir - return zone_id==4075; + return zone_id==4075 ? 0 : SPELL_FAILED_REQUIRES_AREA; } if(mask & ELIXIR_UNSTABLE_MASK) { // in the Blade's Edge Mountains Plateaus and Gruul's Lair. - return zone_id ==3522 || map_id==565; + return zone_id ==3522 || map_id==565 ? 0 : SPELL_FAILED_INCORRECT_AREA; } if(mask & ELIXIR_SHATTRATH_MASK) { // in Tempest Keep, Serpentshrine Cavern, Caverns of Time: Mount Hyjal, Black Temple, Sunwell Plateau if(zone_id ==3607 || map_id==534 || map_id==564 || zone_id==4075) - return true; + return 0; MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); if(!mapEntry) - return false; + return SPELL_FAILED_INCORRECT_AREA; - return mapEntry->multimap_id==206; + return mapEntry->multimap_id==206 ? 0 : SPELL_FAILED_INCORRECT_AREA; } // elixirs not have another limitations - return true; + return 0; } } @@ -2424,35 +2690,104 @@ bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 z { MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); if(!mapEntry) - return false; + return SPELL_FAILED_INCORRECT_AREA; - return mapEntry->multimap_id==206; + return mapEntry->multimap_id==206 ? 0 : SPELL_FAILED_REQUIRES_AREA; } case 41617: // Cenarion Mana Salve case 41619: // Cenarion Healing Salve { MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); if(!mapEntry) - return false; + return SPELL_FAILED_INCORRECT_AREA; - return mapEntry->multimap_id==207; + return mapEntry->multimap_id==207 ? 0 : SPELL_FAILED_REQUIRES_AREA; } case 40216: // Dragonmaw Illusion case 42016: // Dragonmaw Illusion - return area_id == 3759 || area_id == 3966 || area_id == 3939; + return area_id == 3759 || area_id == 3966 || area_id == 3939 ? 0 : SPELL_FAILED_INCORRECT_AREA; + case 51721: // Dominion Over Acherus + case 54055: // Dominion Over Acherus + return area_id == 4281 || area_id == 4342 ? 0 : SPELL_FAILED_INCORRECT_AREA; + case 51852: // The Eye of Acherus + return map_id == 609 ? 0 : SPELL_FAILED_REQUIRES_AREA; + case 54119: // Mist of the Kvaldir + return area_id == 4028 || area_id == 4029 || area_id == 4106 || area_id == 4031 ? 0 : SPELL_FAILED_INCORRECT_AREA; + case 23333: // Warsong Flag + case 23335: // Silverwing Flag + return map_id == 489 && bgInstanceId ? 0 : SPELL_FAILED_REQUIRES_AREA; + case 34976: // Netherstorm Flag + return map_id == 566 && bgInstanceId ? 0 : SPELL_FAILED_REQUIRES_AREA; + case 2584: // Waiting to Resurrect + case 22011: // Spirit Heal Channel + case 22012: // Spirit Heal + case 24171: // Resurrection Impact Visual + case 42792: // Recently Dropped Flag + case 43681: // Inactive + case 44535: // Spirit Heal (mana) + { + MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); + if(!mapEntry) + return SPELL_FAILED_INCORRECT_AREA; + + return mapEntry->IsBattleGround() && bgInstanceId ? 0 : SPELL_FAILED_REQUIRES_AREA; + } + case 44521: // Preparation + { + if(!bgInstanceId) + return SPELL_FAILED_REQUIRES_AREA; + + MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); + if(!mapEntry) + return SPELL_FAILED_INCORRECT_AREA; + + if(!mapEntry->IsBattleGround()) + return SPELL_FAILED_REQUIRES_AREA; + + BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgInstanceId); + return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? 0 : SPELL_FAILED_REQUIRES_AREA; + } + case 32724: // Gold Team (Alliance) + case 32725: // Green Team (Alliance) + case 35774: // Gold Team (Horde) + case 35775: // Green Team (Horde) + { + MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); + if(!mapEntry) + return SPELL_FAILED_INCORRECT_AREA; + + return mapEntry->IsBattleArena() && bgInstanceId ? 0 : SPELL_FAILED_REQUIRES_AREA; + } + case 32727: // Arena Preparation + { + if(!bgInstanceId) + return SPELL_FAILED_REQUIRES_AREA; + + MapEntry const* mapEntry = sMapStore.LookupEntry(map_id); + if(!mapEntry) + return SPELL_FAILED_INCORRECT_AREA; + + if(!mapEntry->IsBattleArena()) + return SPELL_FAILED_REQUIRES_AREA; + + BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgInstanceId); + return bg && bg->GetStatus()==STATUS_WAIT_JOIN ? 0 : SPELL_FAILED_REQUIRES_AREA; + } } - return true; + return 0; } void SpellMgr::LoadSkillLineAbilityMap() { mSkillLineAbilityMap.clear(); + barGoLink bar( sSkillLineAbilityStore.GetNumRows() ); uint32 count = 0; for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); i++) { + bar.step(); SkillLineAbilityEntry const *SkillInfo = sSkillLineAbilityStore.LookupEntry(i); if(!SkillInfo) continue; @@ -2462,7 +2797,7 @@ void SpellMgr::LoadSkillLineAbilityMap() } sLog.outString(); - sLog.outString(">> Loaded %u SkillLineAbility MultiMap", count); + sLog.outString(">> Loaded %u SkillLineAbility MultiMap Data", count); } DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto, bool triggered) @@ -2470,56 +2805,49 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto // Explicit Diminishing Groups switch(spellproto->SpellFamilyName) { - case SPELLFAMILY_MAGE: - { - // Polymorph - if ((spellproto->SpellFamilyFlags & 0x00001000000LL) && spellproto->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE) - return DIMINISHING_POLYMORPH; - break; - } case SPELLFAMILY_ROGUE: { // Kidney Shot - if (spellproto->SpellFamilyFlags & 0x00000200000LL) + if (spellproto->SpellFamilyFlags[0] & 0x200000) return DIMINISHING_KIDNEYSHOT; // Sap - else if (spellproto->SpellFamilyFlags & 0x00000000080LL) + else if (spellproto->SpellFamilyFlags[0] & 0x80) return DIMINISHING_POLYMORPH; // Gouge - else if (spellproto->SpellFamilyFlags & 0x00000000008LL) + else if (spellproto->SpellFamilyFlags[0] & 0x8) return DIMINISHING_POLYMORPH; // Blind - else if (spellproto->SpellFamilyFlags & 0x00001000000LL) + else if (spellproto->SpellFamilyFlags[0] & 0x00001000000) return DIMINISHING_BLIND_CYCLONE; break; } case SPELLFAMILY_WARLOCK: { // Death Coil - if (spellproto->SpellFamilyFlags & 0x00000080000LL) + if (spellproto->SpellFamilyFlags[0] & 0x00000080000) return DIMINISHING_DEATHCOIL; // Seduction - if (spellproto->SpellFamilyFlags & 0x00040000000LL) + if (spellproto->SpellFamilyFlags[0] & 0x00040000000) return DIMINISHING_FEAR; // Fear //else if (spellproto->SpellFamilyFlags & 0x40840000000LL) // return DIMINISHING_WARLOCK_FEAR; // Curses/etc - else if (spellproto->SpellFamilyFlags & 0x00080000000LL) + else if (spellproto->SpellFamilyFlags[0] & 0x80000000) return DIMINISHING_LIMITONLY; break; } case SPELLFAMILY_DRUID: { // Cyclone - if (spellproto->SpellFamilyFlags & 0x02000000000LL) + if (spellproto->SpellFamilyFlags[1] & 0x020) return DIMINISHING_BLIND_CYCLONE; break; } case SPELLFAMILY_WARRIOR: { // Hamstring - limit duration to 10s in PvP - if (spellproto->SpellFamilyFlags & 0x00000000002LL) + if (spellproto->SpellFamilyFlags[0] & 0x00000000002) return DIMINISHING_LIMITONLY; break; } @@ -2528,30 +2856,21 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto } // Get by mechanic - for (uint8 i=0;i<3;++i) - { - if (spellproto->Mechanic == MECHANIC_STUN || spellproto->EffectMechanic[i] == MECHANIC_STUN) - return triggered ? DIMINISHING_TRIGGER_STUN : DIMINISHING_CONTROL_STUN; - else if (spellproto->Mechanic == MECHANIC_SLEEP || spellproto->EffectMechanic[i] == MECHANIC_SLEEP) - return DIMINISHING_SLEEP; - else if (spellproto->Mechanic == MECHANIC_ROOT || spellproto->EffectMechanic[i] == MECHANIC_ROOT) - return triggered ? DIMINISHING_TRIGGER_ROOT : DIMINISHING_CONTROL_ROOT; - else if (spellproto->Mechanic == MECHANIC_FEAR || spellproto->EffectMechanic[i] == MECHANIC_FEAR) - return DIMINISHING_FEAR; - else if (spellproto->Mechanic == MECHANIC_CHARM || spellproto->EffectMechanic[i] == MECHANIC_CHARM) - return DIMINISHING_CHARM; - else if (spellproto->Mechanic == MECHANIC_SILENCE || spellproto->EffectMechanic[i] == MECHANIC_SILENCE) - return DIMINISHING_SILENCE; - else if (spellproto->Mechanic == MECHANIC_DISARM || spellproto->EffectMechanic[i] == MECHANIC_DISARM) - return DIMINISHING_DISARM; - else if (spellproto->Mechanic == MECHANIC_FREEZE || spellproto->EffectMechanic[i] == MECHANIC_FREEZE) - return DIMINISHING_FREEZE; - else if (spellproto->Mechanic == MECHANIC_KNOCKOUT|| spellproto->EffectMechanic[i] == MECHANIC_KNOCKOUT || - spellproto->Mechanic == MECHANIC_SAPPED || spellproto->EffectMechanic[i] == MECHANIC_SAPPED) - return DIMINISHING_KNOCKOUT; - else if (spellproto->Mechanic == MECHANIC_BANISH || spellproto->EffectMechanic[i] == MECHANIC_BANISH) - return DIMINISHING_BANISH; - } + uint32 mechanic = GetAllSpellMechanicMask(spellproto); + if (mechanic == MECHANIC_NONE) return DIMINISHING_NONE; + if (mechanic & (1<<MECHANIC_STUN)) return triggered ? DIMINISHING_TRIGGER_STUN : DIMINISHING_CONTROL_STUN; + if (mechanic & (1<<MECHANIC_SLEEP)) return DIMINISHING_SLEEP; + if (mechanic & (1<<MECHANIC_POLYMORPH)) return DIMINISHING_POLYMORPH; + if (mechanic & (1<<MECHANIC_ROOT)) return triggered ? DIMINISHING_TRIGGER_ROOT : DIMINISHING_CONTROL_ROOT; + if (mechanic & (1<<MECHANIC_FEAR)) return DIMINISHING_FEAR; + if (mechanic & (1<<MECHANIC_CHARM)) return DIMINISHING_CHARM; + if (mechanic & (1<<MECHANIC_SILENCE)) return DIMINISHING_SILENCE; + if (mechanic & (1<<DIMINISHING_DISARM)) return DIMINISHING_DISARM; + if (mechanic & (1<<MECHANIC_FREEZE)) return DIMINISHING_FREEZE; + if (mechanic & ((1<<MECHANIC_KNOCKOUT) | (1<<MECHANIC_SAPPED))) return DIMINISHING_KNOCKOUT; + if (mechanic & (1<<MECHANIC_BANISH)) return DIMINISHING_BANISH; + if (mechanic & (1<<MECHANIC_HORROR)) return DIMINISHING_DEATHCOIL; + return DIMINISHING_NONE; } diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 747f40c064f..37a79c6adf6 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,12 +10,12 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _SPELLMGR_H @@ -29,6 +29,9 @@ #include "Database/SQLStorage.h" #include "Utilities/UnorderedMap.h" + +#include "Player.h" + #include <map> class Player; @@ -38,175 +41,188 @@ extern SQLStorage sSpellThreatStore; enum SpellFailedReason { - SPELL_FAILED_AFFECTING_COMBAT = 0x00, - SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 0x01, - SPELL_FAILED_ALREADY_AT_FULL_MANA = 0x02, - SPELL_FAILED_ALREADY_AT_FULL_POWER = 0x03, - SPELL_FAILED_ALREADY_BEING_TAMED = 0x04, - SPELL_FAILED_ALREADY_HAVE_CHARM = 0x05, - SPELL_FAILED_ALREADY_HAVE_SUMMON = 0x06, - SPELL_FAILED_ALREADY_OPEN = 0x07, - SPELL_FAILED_AURA_BOUNCED = 0x08, - SPELL_FAILED_AUTOTRACK_INTERRUPTED = 0x09, - SPELL_FAILED_BAD_IMPLICIT_TARGETS = 0x0A, - SPELL_FAILED_BAD_TARGETS = 0x0B, - SPELL_FAILED_CANT_BE_CHARMED = 0x0C, - SPELL_FAILED_CANT_BE_DISENCHANTED = 0x0D, - SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 0x0E, - SPELL_FAILED_CANT_BE_PROSPECTED = 0x0F, - SPELL_FAILED_CANT_CAST_ON_TAPPED = 0x10, - SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 0x11, - SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 0x12, - SPELL_FAILED_CANT_STEALTH = 0x13, - SPELL_FAILED_CASTER_AURASTATE = 0x14, - SPELL_FAILED_CASTER_DEAD = 0x15, - SPELL_FAILED_CHARMED = 0x16, - SPELL_FAILED_CHEST_IN_USE = 0x17, - SPELL_FAILED_CONFUSED = 0x18, - SPELL_FAILED_DONT_REPORT = 0x19, - SPELL_FAILED_EQUIPPED_ITEM = 0x1A, - SPELL_FAILED_EQUIPPED_ITEM_CLASS = 0x1B, - SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 0x1C, - SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 0x1D, - SPELL_FAILED_ERROR = 0x1E, - SPELL_FAILED_FIZZLE = 0x1F, - SPELL_FAILED_FLEEING = 0x20, - SPELL_FAILED_FOOD_LOWLEVEL = 0x21, - SPELL_FAILED_HIGHLEVEL = 0x22, - SPELL_FAILED_HUNGER_SATIATED = 0x23, - SPELL_FAILED_IMMUNE = 0x24, - SPELL_FAILED_INTERRUPTED = 0x25, - SPELL_FAILED_INTERRUPTED_COMBAT = 0x26, - SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 0x27, - SPELL_FAILED_ITEM_GONE = 0x28, - SPELL_FAILED_ITEM_NOT_FOUND = 0x29, - SPELL_FAILED_ITEM_NOT_READY = 0x2A, - SPELL_FAILED_LEVEL_REQUIREMENT = 0x2B, - SPELL_FAILED_LINE_OF_SIGHT = 0x2C, - SPELL_FAILED_LOWLEVEL = 0x2D, - SPELL_FAILED_LOW_CASTLEVEL = 0x2E, - SPELL_FAILED_MAINHAND_EMPTY = 0x2F, - SPELL_FAILED_MOVING = 0x30, - SPELL_FAILED_NEED_AMMO = 0x31, - SPELL_FAILED_NEED_AMMO_POUCH = 0x32, - SPELL_FAILED_NEED_EXOTIC_AMMO = 0x33, - SPELL_FAILED_NOPATH = 0x34, - SPELL_FAILED_NOT_BEHIND = 0x35, - SPELL_FAILED_NOT_FISHABLE = 0x36, - SPELL_FAILED_NOT_FLYING = 0x37, - SPELL_FAILED_NOT_HERE = 0x38, - SPELL_FAILED_NOT_INFRONT = 0x39, - SPELL_FAILED_NOT_IN_CONTROL = 0x3A, - SPELL_FAILED_NOT_KNOWN = 0x3B, - SPELL_FAILED_NOT_MOUNTED = 0x3C, - SPELL_FAILED_NOT_ON_TAXI = 0x3D, - SPELL_FAILED_NOT_ON_TRANSPORT = 0x3E, - SPELL_FAILED_NOT_READY = 0x3F, - SPELL_FAILED_NOT_SHAPESHIFT = 0x40, - SPELL_FAILED_NOT_STANDING = 0x41, - SPELL_FAILED_NOT_TRADEABLE = 0x42, - SPELL_FAILED_NOT_TRADING = 0x43, - SPELL_FAILED_NOT_UNSHEATHED = 0x44, - SPELL_FAILED_NOT_WHILE_GHOST = 0x45, - SPELL_FAILED_NO_AMMO = 0x46, - SPELL_FAILED_NO_CHARGES_REMAIN = 0x47, - SPELL_FAILED_NO_CHAMPION = 0x48, - SPELL_FAILED_NO_COMBO_POINTS = 0x49, - SPELL_FAILED_NO_DUELING = 0x4A, - SPELL_FAILED_NO_ENDURANCE = 0x4B, - SPELL_FAILED_NO_FISH = 0x4C, - SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 0x4D, - SPELL_FAILED_NO_MOUNTS_ALLOWED = 0x4E, - SPELL_FAILED_NO_PET = 0x4F, - SPELL_FAILED_NO_POWER = 0x50, - SPELL_FAILED_NOTHING_TO_DISPEL = 0x51, - SPELL_FAILED_NOTHING_TO_STEAL = 0x52, - SPELL_FAILED_ONLY_ABOVEWATER = 0x53, - SPELL_FAILED_ONLY_DAYTIME = 0x54, - SPELL_FAILED_ONLY_INDOORS = 0x55, - SPELL_FAILED_ONLY_MOUNTED = 0x56, - SPELL_FAILED_ONLY_NIGHTTIME = 0x57, - SPELL_FAILED_ONLY_OUTDOORS = 0x58, - SPELL_FAILED_ONLY_SHAPESHIFT = 0x59, - SPELL_FAILED_ONLY_STEALTHED = 0x5A, - SPELL_FAILED_ONLY_UNDERWATER = 0x5B, - SPELL_FAILED_OUT_OF_RANGE = 0x5C, - SPELL_FAILED_PACIFIED = 0x5D, - SPELL_FAILED_POSSESSED = 0x5E, - SPELL_FAILED_REAGENTS = 0x5F, - SPELL_FAILED_REQUIRES_AREA = 0x60, - SPELL_FAILED_REQUIRES_SPELL_FOCUS = 0x61, - SPELL_FAILED_ROOTED = 0x62, - SPELL_FAILED_SILENCED = 0x63, - SPELL_FAILED_SPELL_IN_PROGRESS = 0x64, - SPELL_FAILED_SPELL_LEARNED = 0x65, - SPELL_FAILED_SPELL_UNAVAILABLE = 0x66, - SPELL_FAILED_STUNNED = 0x67, - SPELL_FAILED_TARGETS_DEAD = 0x68, - SPELL_FAILED_TARGET_AFFECTING_COMBAT = 0x69, - SPELL_FAILED_TARGET_AURASTATE = 0x6A, - SPELL_FAILED_TARGET_DUELING = 0x6B, - SPELL_FAILED_TARGET_ENEMY = 0x6C, - SPELL_FAILED_TARGET_ENRAGED = 0x6D, - SPELL_FAILED_TARGET_FRIENDLY = 0x6E, - SPELL_FAILED_TARGET_IN_COMBAT = 0x6F, - SPELL_FAILED_TARGET_IS_PLAYER = 0x70, - SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 0x71, - SPELL_FAILED_TARGET_NOT_DEAD = 0x72, - SPELL_FAILED_TARGET_NOT_IN_PARTY = 0x73, - SPELL_FAILED_TARGET_NOT_LOOTED = 0x74, - SPELL_FAILED_TARGET_NOT_PLAYER = 0x75, - SPELL_FAILED_TARGET_NO_POCKETS = 0x76, - SPELL_FAILED_TARGET_NO_WEAPONS = 0x77, - SPELL_FAILED_TARGET_UNSKINNABLE = 0x78, - SPELL_FAILED_THIRST_SATIATED = 0x79, - SPELL_FAILED_TOO_CLOSE = 0x7A, - SPELL_FAILED_TOO_MANY_OF_ITEM = 0x7B, - SPELL_FAILED_TOTEM_CATEGORY = 0x7C, - SPELL_FAILED_TOTEMS = 0x7D, - SPELL_FAILED_TRAINING_POINTS = 0x7E, - SPELL_FAILED_TRY_AGAIN = 0x7F, - SPELL_FAILED_UNIT_NOT_BEHIND = 0x80, - SPELL_FAILED_UNIT_NOT_INFRONT = 0x81, - SPELL_FAILED_WRONG_PET_FOOD = 0x82, - SPELL_FAILED_NOT_WHILE_FATIGUED = 0x83, - SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 0x84, - SPELL_FAILED_NOT_WHILE_TRADING = 0x85, - SPELL_FAILED_TARGET_NOT_IN_RAID = 0x86, - SPELL_FAILED_DISENCHANT_WHILE_LOOTING = 0x87, - SPELL_FAILED_PROSPECT_WHILE_LOOTING = 0x88, - SPELL_FAILED_PROSPECT_NEED_MORE = 0x89, - SPELL_FAILED_TARGET_FREEFORALL = 0x8A, - SPELL_FAILED_NO_EDIBLE_CORPSES = 0x8B, - SPELL_FAILED_ONLY_BATTLEGROUNDS = 0x8C, - SPELL_FAILED_TARGET_NOT_GHOST = 0x8D, - SPELL_FAILED_TOO_MANY_SKILLS = 0x8E, - SPELL_FAILED_TRANSFORM_UNUSABLE = 0x8F, - SPELL_FAILED_WRONG_WEATHER = 0x90, - SPELL_FAILED_DAMAGE_IMMUNE = 0x91, - SPELL_FAILED_PREVENTED_BY_MECHANIC = 0x92, - SPELL_FAILED_PLAY_TIME = 0x93, - SPELL_FAILED_REPUTATION = 0x94, - SPELL_FAILED_MIN_SKILL = 0x95, - SPELL_FAILED_NOT_IN_ARENA = 0x96, - SPELL_FAILED_NOT_ON_SHAPESHIFT = 0x97, - SPELL_FAILED_NOT_ON_STEALTHED = 0x98, - SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 0x99, - SPELL_FAILED_NOT_ON_MOUNTED = 0x9A, - SPELL_FAILED_TOO_SHALLOW = 0x9B, - SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 0x9C, - SPELL_FAILED_TARGET_IS_TRIVIAL = 0x9D, - SPELL_FAILED_BM_OR_INVISGOD = 0x9E, - SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 0x9F, - SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 0xA0, - SPELL_FAILED_NOT_IDLE = 0xA1, - SPELL_FAILED_NOT_INACTIVE = 0xA2, - SPELL_FAILED_PARTIAL_PLAYTIME = 0xA3, - SPELL_FAILED_NO_PLAYTIME = 0xA4, - SPELL_FAILED_NOT_IN_BATTLEGROUND = 0xA5, - SPELL_FAILED_ONLY_IN_ARENA = 0xA6, - SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 0xA7, - SPELL_FAILED_UNKNOWN = 0xA8, + SPELL_FAILED_AFFECTING_COMBAT = 0, + SPELL_FAILED_ALREADY_AT_FULL_HEALTH = 1, + SPELL_FAILED_ALREADY_AT_FULL_MANA = 2, + SPELL_FAILED_ALREADY_AT_FULL_POWER = 3, + SPELL_FAILED_ALREADY_BEING_TAMED = 4, + SPELL_FAILED_ALREADY_HAVE_CHARM = 5, + SPELL_FAILED_ALREADY_HAVE_SUMMON = 6, + SPELL_FAILED_ALREADY_OPEN = 7, + SPELL_FAILED_AURA_BOUNCED = 8, + SPELL_FAILED_AUTOTRACK_INTERRUPTED = 9, + SPELL_FAILED_BAD_IMPLICIT_TARGETS = 10, + SPELL_FAILED_BAD_TARGETS = 11, + SPELL_FAILED_CANT_BE_CHARMED = 12, + SPELL_FAILED_CANT_BE_DISENCHANTED = 13, + SPELL_FAILED_CANT_BE_DISENCHANTED_SKILL = 14, + SPELL_FAILED_CANT_BE_MILLED = 15, + SPELL_FAILED_CANT_BE_PROSPECTED = 16, + SPELL_FAILED_CANT_CAST_ON_TAPPED = 17, + SPELL_FAILED_CANT_DUEL_WHILE_INVISIBLE = 18, + SPELL_FAILED_CANT_DUEL_WHILE_STEALTHED = 19, + SPELL_FAILED_CANT_STEALTH = 20, + SPELL_FAILED_CASTER_AURASTATE = 21, + SPELL_FAILED_CASTER_DEAD = 22, + SPELL_FAILED_CHARMED = 23, + SPELL_FAILED_CHEST_IN_USE = 24, + SPELL_FAILED_CONFUSED = 25, + SPELL_FAILED_DONT_REPORT = 26, + SPELL_FAILED_EQUIPPED_ITEM = 27, + SPELL_FAILED_EQUIPPED_ITEM_CLASS = 28, + SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND = 29, + SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND = 30, + SPELL_FAILED_ERROR = 31, + SPELL_FAILED_FIZZLE = 32, + SPELL_FAILED_FLEEING = 33, + SPELL_FAILED_FOOD_LOWLEVEL = 34, + SPELL_FAILED_HIGHLEVEL = 35, + SPELL_FAILED_HUNGER_SATIATED = 36, + SPELL_FAILED_IMMUNE = 37, + SPELL_FAILED_INCORRECT_AREA = 38, + SPELL_FAILED_INTERRUPTED = 39, + SPELL_FAILED_INTERRUPTED_COMBAT = 40, + SPELL_FAILED_ITEM_ALREADY_ENCHANTED = 41, + SPELL_FAILED_ITEM_GONE = 42, + SPELL_FAILED_ITEM_NOT_FOUND = 43, + SPELL_FAILED_ITEM_NOT_READY = 44, + SPELL_FAILED_LEVEL_REQUIREMENT = 45, + SPELL_FAILED_LINE_OF_SIGHT = 46, + SPELL_FAILED_LOWLEVEL = 47, + SPELL_FAILED_LOW_CASTLEVEL = 48, + SPELL_FAILED_MAINHAND_EMPTY = 49, + SPELL_FAILED_MOVING = 50, + SPELL_FAILED_NEED_AMMO = 51, + SPELL_FAILED_NEED_AMMO_POUCH = 52, + SPELL_FAILED_NEED_EXOTIC_AMMO = 53, + SPELL_FAILED_NEED_MORE_ITEMS = 54, + SPELL_FAILED_NOPATH = 55, + SPELL_FAILED_NOT_BEHIND = 56, + SPELL_FAILED_NOT_FISHABLE = 57, + SPELL_FAILED_NOT_FLYING = 58, + SPELL_FAILED_NOT_HERE = 59, + SPELL_FAILED_NOT_INFRONT = 60, + SPELL_FAILED_NOT_IN_CONTROL = 61, + SPELL_FAILED_NOT_KNOWN = 62, + SPELL_FAILED_NOT_MOUNTED = 63, + SPELL_FAILED_NOT_ON_TAXI = 64, + SPELL_FAILED_NOT_ON_TRANSPORT = 65, + SPELL_FAILED_NOT_READY = 66, + SPELL_FAILED_NOT_SHAPESHIFT = 67, + SPELL_FAILED_NOT_STANDING = 68, + SPELL_FAILED_NOT_TRADEABLE = 69, + SPELL_FAILED_NOT_TRADING = 70, + SPELL_FAILED_NOT_UNSHEATHED = 71, + SPELL_FAILED_NOT_WHILE_GHOST = 72, + SPELL_FAILED_NOT_WHILE_LOOTING = 73, + SPELL_FAILED_NO_AMMO = 74, + SPELL_FAILED_NO_CHARGES_REMAIN = 75, + SPELL_FAILED_NO_CHAMPION = 76, + SPELL_FAILED_NO_COMBO_POINTS = 77, + SPELL_FAILED_NO_DUELING = 78, + SPELL_FAILED_NO_ENDURANCE = 79, + SPELL_FAILED_NO_FISH = 80, + SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED = 81, + SPELL_FAILED_NO_MOUNTS_ALLOWED = 82, + SPELL_FAILED_NO_PET = 83, + SPELL_FAILED_NO_POWER = 84, + SPELL_FAILED_NOTHING_TO_DISPEL = 85, + SPELL_FAILED_NOTHING_TO_STEAL = 86, + SPELL_FAILED_ONLY_ABOVEWATER = 87, + SPELL_FAILED_ONLY_DAYTIME = 88, + SPELL_FAILED_ONLY_INDOORS = 89, + SPELL_FAILED_ONLY_MOUNTED = 90, + SPELL_FAILED_ONLY_NIGHTTIME = 91, + SPELL_FAILED_ONLY_OUTDOORS = 92, + SPELL_FAILED_ONLY_SHAPESHIFT = 93, + SPELL_FAILED_ONLY_STEALTHED = 94, + SPELL_FAILED_ONLY_UNDERWATER = 95, + SPELL_FAILED_OUT_OF_RANGE = 96, + SPELL_FAILED_PACIFIED = 97, + SPELL_FAILED_POSSESSED = 98, + SPELL_FAILED_REAGENTS = 99, + SPELL_FAILED_REQUIRES_AREA = 100, + SPELL_FAILED_REQUIRES_SPELL_FOCUS = 101, + SPELL_FAILED_ROOTED = 102, + SPELL_FAILED_SILENCED = 103, + SPELL_FAILED_SPELL_IN_PROGRESS = 104, + SPELL_FAILED_SPELL_LEARNED = 105, + SPELL_FAILED_SPELL_UNAVAILABLE = 106, + SPELL_FAILED_STUNNED = 107, + SPELL_FAILED_TARGETS_DEAD = 108, + SPELL_FAILED_TARGET_AFFECTING_COMBAT = 109, + SPELL_FAILED_TARGET_AURASTATE = 110, + SPELL_FAILED_TARGET_DUELING = 111, + SPELL_FAILED_TARGET_ENEMY = 112, + SPELL_FAILED_TARGET_ENRAGED = 113, + SPELL_FAILED_TARGET_FRIENDLY = 114, + SPELL_FAILED_TARGET_IN_COMBAT = 115, + SPELL_FAILED_TARGET_IS_PLAYER = 116, + SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED = 117, + SPELL_FAILED_TARGET_NOT_DEAD = 118, + SPELL_FAILED_TARGET_NOT_IN_PARTY = 119, + SPELL_FAILED_TARGET_NOT_LOOTED = 120, + SPELL_FAILED_TARGET_NOT_PLAYER = 121, + SPELL_FAILED_TARGET_NO_POCKETS = 122, + SPELL_FAILED_TARGET_NO_WEAPONS = 123, + SPELL_FAILED_TARGET_NO_RANGED_WEAPONS = 124, + SPELL_FAILED_TARGET_UNSKINNABLE = 125, + SPELL_FAILED_THIRST_SATIATED = 126, + SPELL_FAILED_TOO_CLOSE = 127, + SPELL_FAILED_TOO_MANY_OF_ITEM = 128, + SPELL_FAILED_TOTEM_CATEGORY = 129, + SPELL_FAILED_TOTEMS = 130, + SPELL_FAILED_TRY_AGAIN = 131, + SPELL_FAILED_UNIT_NOT_BEHIND = 132, + SPELL_FAILED_UNIT_NOT_INFRONT = 133, + SPELL_FAILED_WRONG_PET_FOOD = 134, + SPELL_FAILED_NOT_WHILE_FATIGUED = 135, + SPELL_FAILED_TARGET_NOT_IN_INSTANCE = 136, + SPELL_FAILED_NOT_WHILE_TRADING = 137, + SPELL_FAILED_TARGET_NOT_IN_RAID = 138, + SPELL_FAILED_TARGET_FREEFORALL = 139, + SPELL_FAILED_NO_EDIBLE_CORPSES = 140, + SPELL_FAILED_ONLY_BATTLEGROUNDS = 141, + SPELL_FAILED_TARGET_NOT_GHOST = 142, + SPELL_FAILED_TRANSFORM_UNUSABLE = 143, + SPELL_FAILED_WRONG_WEATHER = 144, + SPELL_FAILED_DAMAGE_IMMUNE = 145, + SPELL_FAILED_PREVENTED_BY_MECHANIC = 146, + SPELL_FAILED_PLAY_TIME = 147, + SPELL_FAILED_REPUTATION = 148, + SPELL_FAILED_MIN_SKILL = 149, + SPELL_FAILED_NOT_IN_ARENA = 150, + SPELL_FAILED_NOT_ON_SHAPESHIFT = 151, + SPELL_FAILED_NOT_ON_STEALTHED = 152, + SPELL_FAILED_NOT_ON_DAMAGE_IMMUNE = 153, + SPELL_FAILED_NOT_ON_MOUNTED = 154, + SPELL_FAILED_TOO_SHALLOW = 155, + SPELL_FAILED_TARGET_NOT_IN_SANCTUARY = 156, + SPELL_FAILED_TARGET_IS_TRIVIAL = 157, + SPELL_FAILED_BM_OR_INVISGOD = 158, + SPELL_FAILED_EXPERT_RIDING_REQUIREMENT = 159, + SPELL_FAILED_ARTISAN_RIDING_REQUIREMENT = 160, + SPELL_FAILED_NOT_IDLE = 161, + SPELL_FAILED_NOT_INACTIVE = 162, + SPELL_FAILED_PARTIAL_PLAYTIME = 163, + SPELL_FAILED_NO_PLAYTIME = 164, + SPELL_FAILED_NOT_IN_BATTLEGROUND = 165, + SPELL_FAILED_NOT_IN_RAID_INSTANCE = 166, + SPELL_FAILED_ONLY_IN_ARENA = 167, + SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE = 168, + SPELL_FAILED_ON_USE_ENCHANT = 169, + SPELL_FAILED_NOT_ON_GROUND = 170, + SPELL_FAILED_CUSTOM_ERROR = 171, + SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW = 172, + SPELL_FAILED_TOO_MANY_SOCKETS = 173, + SPELL_FAILED_INVALID_GLYPH = 174, + SPELL_FAILED_UNIQUE_GLYPH = 175, + SPELL_FAILED_GLYPH_SOCKET_LOCKED = 176, + SPELL_FAILED_NO_VALID_TARGETS = 177, + SPELL_FAILED_ITEM_AT_MAX_CHARGES = 178, + SPELL_FAILED_NOT_IN_BARBERSHOP = 179, + SPELL_FAILED_FISHING_TOO_LOW = 180, + SPELL_FAILED_UNKNOWN = 181 }; enum SpellFamilyNames @@ -223,8 +239,12 @@ enum SpellFamilyNames SPELLFAMILY_HUNTER = 9, SPELLFAMILY_PALADIN = 10, SPELLFAMILY_SHAMAN = 11, - SPELLFAMILY_UNK2 = 12, - SPELLFAMILY_POTION = 13 + SPELLFAMILY_UNK2 = 12, // 2 spells (silence resistance) + SPELLFAMILY_POTION = 13, + // 14 - unused + SPELLFAMILY_DEATHKNIGHT = 15, + // 16 - unused + SPELLFAMILY_PET = 17 }; enum SpellDisableTypes @@ -255,15 +275,15 @@ enum SpellSelectTargetTypes }; //Some SpellFamilyFlags -#define SPELLFAMILYFLAG_ROGUE_VANISH 0x000000800LL -#define SPELLFAMILYFLAG_ROGUE_STEALTH 0x000400000LL -#define SPELLFAMILYFLAG_ROGUE_BACKSTAB 0x000800004LL -#define SPELLFAMILYFLAG_ROGUE_SAP 0x000000080LL -#define SPELLFAMILYFLAG_ROGUE_FEINT 0x008000000LL -#define SPELLFAMILYFLAG_ROGUE_KIDNEYSHOT 0x000200000LL -#define SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE 0x9003E0000LL -#define SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR 0x000004000LL -#define SPELLFAMILYFLAG_SHAMAN_FROST_SHOCK 0x080000000LL +#define SPELLFAMILYFLAG_ROGUE_VANISH 0x00000800 +#define SPELLFAMILYFLAG_ROGUE_STEALTH 0x00400000 +#define SPELLFAMILYFLAG_ROGUE_BACKSTAB 0x00800004 +#define SPELLFAMILYFLAG_ROGUE_SAP 0x00000080 +#define SPELLFAMILYFLAG_ROGUE_FEINT 0x08000000 +#define SPELLFAMILYFLAG_ROGUE_KIDNEYSHOT 0x00200000 +//#define SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE 0x9003E0000LL +#define SPELLFAMILYFLAG_WARRIOR_SUNDERARMOR 0x00004000 +#define SPELLFAMILYFLAG_SHAMAN_FROST_SHOCK 0x80000000 // Spell clasification enum SpellSpecific @@ -288,7 +308,8 @@ enum SpellSpecific SPELL_WARLOCK_CORRUPTION= 17, SPELL_WELL_FED = 18, SPELL_DRINK = 19, - SPELL_FOOD = 20 + SPELL_FOOD = 20, + SPELL_PRESENCE = 21, }; #define SPELL_LINKED_MAX_SPELLS 200000 @@ -327,13 +348,27 @@ inline bool IsSealSpell(SpellEntry const *spellInfo) { //Collection of all the seal family flags. No other paladin spell has any of those. return spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && - ( spellInfo->SpellFamilyFlags & 0x4000A000200LL ); + ( spellInfo->SpellFamilyFlags[1] & 0x26000C00 + || spellInfo->SpellFamilyFlags[0] & 0x0A000000 ); } inline bool IsElementalShield(SpellEntry const *spellInfo) { // family flags 10 (Lightning), 42 (Earth), 37 (Water), proc shield from T2 8 pieces bonus - return (spellInfo->SpellFamilyFlags & 0x42000000400LL) || spellInfo->Id == 23552; + return (spellInfo->SpellFamilyFlags[1] & 0x420 + || spellInfo->SpellFamilyFlags[0] & 0x00000400) + || spellInfo->Id == 23552; +} + +inline bool IsExplicitDiscoverySpell(SpellEntry const *spellInfo) +{ + return spellInfo->Effect[0]==SPELL_EFFECT_CREATE_ITEM_2 && spellInfo->Effect[1]==SPELL_EFFECT_SCRIPT_EFFECT; +} + +inline bool IsLootCraftingSpell(SpellEntry const *spellInfo) +{ + return spellInfo->Effect[0]==SPELL_EFFECT_CREATE_ITEM_2 && + (spellInfo->Effect[1]==SPELL_EFFECT_SCRIPT_EFFECT || !spellInfo->EffectItemType[0]); } int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2); @@ -341,6 +376,15 @@ bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1, uint32 spellSpec2); bool IsSingleFromSpellSpecificPerTarget(uint32 spellSpec1, uint32 spellSpec2); bool IsPassiveSpell(uint32 spellId); +inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto) +{ + if(!IsPassiveSpell(spellProto->Id)) + return false; + + return !IsSpellHaveEffect(spellProto,SPELL_EFFECT_APPLY_AURA); +} + + inline bool IsDeathPersistentSpell(SpellEntry const *spellInfo) { switch(spellInfo->Id) @@ -368,9 +412,10 @@ bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellI bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId); -bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id); +uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id,uint32 bgInstanceId); extern bool IsAreaEffectTarget[TOTAL_SPELL_TARGETS]; + inline bool IsAreaOfEffectSpell(SpellEntry const *spellInfo) { if(IsAreaEffectTarget[spellInfo->EffectImplicitTargetA[0]] || IsAreaEffectTarget[spellInfo->EffectImplicitTargetB[0]]) @@ -385,6 +430,7 @@ inline bool IsAreaOfEffectSpell(SpellEntry const *spellInfo) inline bool IsAreaAuraEffect(uint32 effect) { if( effect == SPELL_EFFECT_APPLY_AREA_AURA_PARTY || + effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID || effect == SPELL_EFFECT_APPLY_AREA_AURA_FRIEND || effect == SPELL_EFFECT_APPLY_AREA_AURA_ENEMY || effect == SPELL_EFFECT_APPLY_AREA_AURA_PET || @@ -417,6 +463,11 @@ inline bool isSpellBreakStealth(SpellEntry const* spellInfo) return !(spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_BREAK_STEALTH); } +inline bool IsAutoRepeatRangedSpell(SpellEntry const* spellInfo) +{ + return (spellInfo->Attributes & SPELL_ATTR_RANGED) && (spellInfo->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG); +} + uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form); inline bool IsChanneledSpell(SpellEntry const* spellInfo) @@ -444,6 +495,17 @@ inline uint32 GetSpellMechanicMask(SpellEntry const* spellInfo, int32 effect) return mask; } +inline uint32 GetAllSpellMechanicMask(SpellEntry const* spellInfo) +{ + uint32 mask = 0; + if (spellInfo->Mechanic) + mask |= 1<<spellInfo->Mechanic; + for (int i=0; i< 3; ++i) + if (spellInfo->EffectMechanic[i]) + mask |= 1<<spellInfo->EffectMechanic[i]; + return mask; +} + inline Mechanics GetEffectMechanic(SpellEntry const* spellInfo, int32 effect) { if (spellInfo->EffectMechanic[effect]) @@ -468,7 +530,7 @@ bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group); DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group); // Spell affects related declarations (accessed using SpellMgr functions) -typedef std::map<uint32, uint64> SpellAffectMap; +typedef UNORDERED_MAP<uint32, flag96> SpellAffectMap; // Spell proc event related declarations (accessed using SpellMgr functions) enum ProcFlags @@ -476,16 +538,16 @@ enum ProcFlags PROC_FLAG_NONE = 0x00000000, PROC_FLAG_KILLED = 0x00000001, // 00 Killed by agressor - PROC_FLAG_KILL_AND_GET_XP = 0x00000002, // 01 Kill that yields experience or honor + PROC_FLAG_KILL = 0x00000002, // 01 Kill target (in most cases need XP/Honor reward) - PROC_FLAG_SUCCESSFUL_MILEE_HIT = 0x00000004, // 02 Successful melee attack - PROC_FLAG_TAKEN_MELEE_HIT = 0x00000008, // 03 Taken damage from melee strike hit + PROC_FLAG_SUCCESSFUL_MILEE_HIT = 0x00000004, // 02 Successful melee auto attack + PROC_FLAG_TAKEN_MELEE_HIT = 0x00000008, // 03 Taken damage from melee auto attack hit PROC_FLAG_SUCCESSFUL_MELEE_SPELL_HIT = 0x00000010, // 04 Successful attack by Spell that use melee weapon PROC_FLAG_TAKEN_MELEE_SPELL_HIT = 0x00000020, // 05 Taken damage by Spell that use melee weapon - PROC_FLAG_SUCCESSFUL_RANGED_HIT = 0x00000040, // 06 Successful Ranged attack (all ranged attack deal as spell so newer set :( ) - PROC_FLAG_TAKEN_RANGED_HIT = 0x00000080, // 07 Taken damage from ranged attack (all ranged attack deal as spell so newer set :( ) + PROC_FLAG_SUCCESSFUL_RANGED_HIT = 0x00000040, // 06 Successful Ranged auto attack + PROC_FLAG_TAKEN_RANGED_HIT = 0x00000080, // 07 Taken damage from ranged auto attack PROC_FLAG_SUCCESSFUL_RANGED_SPELL_HIT = 0x00000100, // 08 Successful Ranged attack by Spell that use ranged weapon PROC_FLAG_TAKEN_RANGED_SPELL_HIT = 0x00000200, // 09 Taken damage by Spell that use ranged weapon @@ -536,19 +598,20 @@ enum ProcFlagsEx PROC_EX_DEFLECT = 0x0000200, PROC_EX_ABSORB = 0x0000400, PROC_EX_REFLECT = 0x0000800, - PROC_EX_INTERRUPT = 0x0001000, // Melle hit result can be Interrupt (not used) + PROC_EX_INTERRUPT = 0x0001000, // Melee hit result can be Interrupt (not used) PROC_EX_RESERVED1 = 0x0002000, PROC_EX_RESERVED2 = 0x0004000, PROC_EX_RESERVED3 = 0x0008000, PROC_EX_EX_TRIGGER_ALWAYS = 0x0010000, // If set trigger always ( no matter another flags) used for drop charges - PROC_EX_EX_ONE_TIME_TRIGGER = 0x0020000 // If set trigger always but only one time + PROC_EX_EX_ONE_TIME_TRIGGER = 0x0020000 // If set trigger always but only one time (not used) }; struct SpellProcEventEntry { uint32 schoolMask; // if nonzero - bit mask for matching proc condition based on spell candidate's school: Fire=2, Mask=1<<(2-1)=2 uint32 spellFamilyName; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyNamer value - uint64 spellFamilyMask; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags (like auras 107 and 108 do) + flag96 spellFamilyMask; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags (like auras 107 and 108 do) + uint32 spellFamilyMask2; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags2 (like auras 107 and 108 do) uint32 procFlags; // bitmask for matching proc event uint32 procEx; // proc Extend info (see ProcFlagsEx) float ppmRate; // for melee (ranged?) damage spells - proc rate per minute. if zero, falls back to flat chance from Spell.dbc @@ -556,7 +619,15 @@ struct SpellProcEventEntry uint32 cooldown; // hidden cooldown used for some spell proc events, applied to _triggered_spell_ }; +struct SpellBonusEntry +{ + float direct_damage; + float dot_damage; + float ap_bonus; +}; + typedef UNORDERED_MAP<uint32, SpellProcEventEntry> SpellProcEventMap; +typedef UNORDERED_MAP<uint32, SpellBonusEntry> SpellBonusMap; #define ELIXIR_BATTLE_MASK 0x1 #define ELIXIR_GUARDIAN_MASK 0x2 @@ -679,6 +750,7 @@ typedef std::map<uint32, SpellLearnSkillNode> SpellLearnSkillMap; struct SpellLearnSpellNode { uint32 spell; + bool active; // show in spellbook or not bool autoLearned; }; @@ -686,6 +758,9 @@ typedef std::multimap<uint32, SpellLearnSpellNode> SpellLearnSpellMap; typedef std::multimap<uint32, SkillLineAbilityEntry const*> SkillLineAbilityMap; +typedef std::map<uint32, uint32> PetLevelupSpellSet; +typedef std::map<uint32, PetLevelupSpellSet> PetLevelupSpellMap; + inline bool IsPrimaryProfessionSkill(uint32 skill) { SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(skill); @@ -723,6 +798,11 @@ typedef std::vector<uint32> SpellCustomAttribute; typedef std::map<int32, std::vector<int32> > SpellLinkedMap; +inline bool IsProfessionOrRidingSkill(uint32 skill) +{ + return IsProfessionSkill(skill) || skill == SKILL_RIDING; +} + class SpellMgr { // Constructors @@ -733,15 +813,15 @@ class SpellMgr // Accessors (const or static functions) public: // Spell affects - uint64 GetSpellAffectMask(uint16 spellId, uint8 effectId) const + flag96 const*GetSpellAffect(uint16 spellId, uint8 effectId) const { SpellAffectMap::const_iterator itr = mSpellAffectMap.find((spellId<<8) + effectId); if( itr != mSpellAffectMap.end( ) ) - return itr->second; + return &itr->second; return 0; } - bool IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const; + bool IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const; SpellElixirMap const& GetSpellElixirMap() const { return mSpellElixirs; } @@ -778,6 +858,23 @@ class SpellMgr static bool IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active); + // Spell bonus data + SpellBonusEntry const* GetSpellBonusData(uint32 spellId) const + { + // Lookup data + SpellBonusMap::const_iterator itr = mSpellBonusMap.find(spellId); + if( itr != mSpellBonusMap.end( ) ) + return &itr->second; + // Not found, try lookup for 1 spell rank if exist + if (uint32 rank_1 = GetFirstSpellInChain(spellId)) + { + SpellBonusMap::const_iterator itr = mSpellBonusMap.find(rank_1); + if( itr != mSpellBonusMap.end( ) ) + return &itr->second; + } + return NULL; + } + // Spell target coordinates SpellTargetPosition const* GetSpellTargetPosition(uint32 spell_id) const { @@ -822,6 +919,14 @@ class SpellMgr return 0; } + uint32 GetNextSpellInChain(uint32 spell_id) const + { + if(SpellChainNode const* node = GetSpellChainNode(spell_id)) + return node->next; + + return 0; + } + SpellsRequiringSpellMap const& GetSpellsRequiringSpell() const { return mSpellsReqSpell; } // Note: not use rank for compare to spell ranks: spell chains isn't linear order @@ -901,10 +1006,14 @@ class SpellMgr return false; } + static bool IsProfessionOrRidingSpell(uint32 spellId); static bool IsProfessionSpell(uint32 spellId); static bool IsPrimaryProfessionSpell(uint32 spellId); bool IsPrimaryProfessionFirstRankSpell(uint32 spellId) const; + bool IsSkillBonusSpell(uint32 spellId) const; + + // Spell script targets SpellScriptTarget::const_iterator GetBeginSpellScriptTarget(uint32 spell_id) const { @@ -944,11 +1053,6 @@ class SpellMgr return 0; else return mSpellCustomAttr[spell_id]; - /*SpellCustomAttrMap::const_iterator itr = mSpellCustomAttrMap.find(spell_id); - if(itr != mSpellCustomAttrMap.end()) - return itr->second; - else - return 0;*/ } const std::vector<int32> *GetSpellLinked(int32 spell_id) const @@ -960,6 +1064,15 @@ class SpellMgr SpellEffectTargetTypes EffectTargetType[TOTAL_SPELL_EFFECTS]; SpellSelectTargetTypes SpellTargetType[TOTAL_SPELL_TARGETS]; + PetLevelupSpellSet const* GetPetLevelupSpellList(uint32 petFamily) const + { + PetLevelupSpellMap::const_iterator itr = mPetLevelupSpellMap.find(petFamily); + if(itr != mPetLevelupSpellMap.end()) + return &itr->second; + else + return NULL; + } + // Modifiers public: static SpellMgr& Instance(); @@ -973,12 +1086,14 @@ class SpellMgr void LoadSpellAffects(); void LoadSpellElixirs(); void LoadSpellProcEvents(); + void LoadSpellBonusess(); void LoadSpellTargetPositions(); void LoadSpellThreats(); void LoadSkillLineAbilityMap(); void LoadSpellPetAuras(); void LoadSpellCustomAttr(); void LoadSpellLinked(); + void LoadPetLevelupSpellMap(); private: SpellScriptTarget mSpellScriptTarget; @@ -991,10 +1106,12 @@ class SpellMgr SpellAffectMap mSpellAffectMap; SpellElixirMap mSpellElixirs; SpellProcEventMap mSpellProcEventMap; + SpellBonusMap mSpellBonusMap; SkillLineAbilityMap mSkillLineAbilityMap; SpellPetAuraMap mSpellPetAuraMap; SpellCustomAttribute mSpellCustomAttr; SpellLinkedMap mSpellLinkedMap; + PetLevelupSpellMap mPetLevelupSpellMap; }; #define spellmgr SpellMgr::Instance() diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index bd5ab61eeff..8be79c3cfd8 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,24 +51,17 @@ bool Player::UpdateStats(Stats stat) switch(stat) { case STAT_STRENGTH: - UpdateAttackPowerAndDamage(); UpdateShieldBlockValue(); break; case STAT_AGILITY: UpdateArmor(); - UpdateAttackPowerAndDamage(true); - if(getClass() == CLASS_ROGUE || getClass() == CLASS_HUNTER || getClass() == CLASS_DRUID && m_form==FORM_CAT) - UpdateAttackPowerAndDamage(); - UpdateAllCritPercentages(); UpdateDodgePercentage(); break; - case STAT_STAMINA: UpdateMaxHealth(); break; case STAT_INTELLECT: UpdateMaxPower(POWER_MANA); UpdateAllSpellCritChances(); - UpdateAttackPowerAndDamage(true); //SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, only intellect currently UpdateArmor(); //SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently break; @@ -78,11 +71,60 @@ bool Player::UpdateStats(Stats stat) default: break; } + + if (stat == STAT_STRENGTH) + { + UpdateAttackPowerAndDamage(false); + if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, stat)) + UpdateAttackPowerAndDamage(true); + } + else if (stat == STAT_AGILITY) + { + UpdateAttackPowerAndDamage(false); + UpdateAttackPowerAndDamage(true); + } + else + { + // Need update (exist AP from stat auras) + if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT, stat)) + UpdateAttackPowerAndDamage(false); + if (HasAuraTypeWithMiscvalue(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT, stat)) + UpdateAttackPowerAndDamage(true); + } + UpdateSpellDamageAndHealingBonus(); UpdateManaRegen(); + + // Update ratings in exist SPELL_AURA_MOD_RATING_FROM_STAT and only depends from stat + uint32 mask = 0; + AuraList const& modRatingFromStat = GetAurasByType(SPELL_AURA_MOD_RATING_FROM_STAT); + for(AuraList::const_iterator i = modRatingFromStat.begin();i != modRatingFromStat.end(); ++i) + if (Stats((*i)->GetMiscBValue()) == stat) + mask |= (*i)->GetMiscValue(); + if (mask) + { + for (uint32 rating = 0; rating < MAX_COMBAT_RATING; ++rating) + if (mask & (1 << rating)) + ApplyRatingMod(CombatRating(rating), 0, true); + } return true; } +void Player::ApplySpellDamageBonus(int32 amount, bool apply) +{ + m_baseSpellDamage+=apply?amount:-amount; + // For speed just update for client + ApplyModUInt32Value(PLAYER_FIELD_MOD_HEALING_DONE_POS, amount, apply); +} + +void Player::ApplySpellHealingBonus(int32 amount, bool apply) +{ + m_baseSpellHealing+=apply?amount:-amount; + // For speed just update for client + for(int i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; i++) + ApplyModUInt32Value(PLAYER_FIELD_MOD_DAMAGE_DONE_POS+i, amount, apply);; +} + void Player::UpdateSpellDamageAndHealingBonus() { // Magic damage modifiers implemented in Unit::SpellDamageBonus @@ -155,7 +197,7 @@ void Player::UpdateArmor() { Modifier* mod = (*i)->GetModifier(); if(mod->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) - value += int32(GetStat(Stats((*i)->GetMiscBValue())) * (*i)->GetModifierValue() / 100.0f); + value += int32(GetStat(Stats((*i)->GetMiscBValue())) * mod->m_amount / 100.0f); } value *= GetModifierValue(unitMod, TOTAL_PCT); @@ -213,6 +255,12 @@ void Player::UpdateMaxPower(Powers power) SetMaxPower(power, uint32(value)); } +void Player::ApplyFeralAPBonus(int32 amount, bool apply) +{ + m_baseFeralAP+= apply ? amount:-amount; + UpdateAttackPowerAndDamage(); +} + void Player::UpdateAttackPowerAndDamage(bool ranged ) { float val2 = 0.0f; @@ -253,11 +301,12 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) { switch(getClass()) { - case CLASS_WARRIOR: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; - case CLASS_PALADIN: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; - case CLASS_ROGUE: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; - case CLASS_HUNTER: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; - case CLASS_SHAMAN: val2 = level*2.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + case CLASS_WARRIOR: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + case CLASS_PALADIN: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + case CLASS_DEATH_KNIGHT: val2 = level*3.0f + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + case CLASS_ROGUE: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; + case CLASS_HUNTER: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; + case CLASS_SHAMAN: val2 = level*2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; break; case CLASS_DRUID: { //Check if Predatory Strikes is skilled @@ -286,12 +335,12 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) switch(m_form) { case FORM_CAT: - val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f; break; + val2 = getLevel()*(mLevelMult+2.0f) + GetStat(STAT_STRENGTH)*2.0f + GetStat(STAT_AGILITY) - 20.0f + m_baseFeralAP; break; case FORM_BEAR: case FORM_DIREBEAR: - val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + val2 = getLevel()*(mLevelMult+3.0f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break; case FORM_MOONKIN: - val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; + val2 = getLevel()*(mLevelMult+1.5f) + GetStat(STAT_STRENGTH)*2.0f - 20.0f + m_baseFeralAP; break; default: val2 = GetStat(STAT_STRENGTH)*2.0f - 20.0f; break; } @@ -309,17 +358,26 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods - if( ranged && (getClassMask() & CLASSMASK_WAND_USERS)==0) + if( ranged ) + { + if ((getClassMask() & CLASSMASK_WAND_USERS)==0) + { + AuraList const& mRAPbyStat = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); + for(AuraList::const_iterator i = mRAPbyStat.begin();i != mRAPbyStat.end(); ++i) + attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f); + } + } + else { - AuraList const& mRAPbyIntellect = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT); - for(AuraList::const_iterator i = mRAPbyIntellect.begin();i != mRAPbyIntellect.end(); ++i) - attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifierValue() / 100.0f); + AuraList const& mAPbyStat = GetAurasByType(SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT); + for(AuraList::const_iterator i = mAPbyStat.begin();i != mAPbyStat.end(); ++i) + attPowerMod += int32(GetStat(Stats((*i)->GetModifier()->m_miscvalue)) * (*i)->GetModifier()->m_amount / 100.0f); } float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; - SetUInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field - SetUInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field + SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field + SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field //automatically update weapon damage after attack power modification @@ -386,8 +444,15 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, fl weapon_mindamage = lvl*0.85*att_speed; weapon_maxdamage = lvl*1.25*att_speed; } - else if(!IsUseEquipedWeapon(attType==BASE_ATTACK)) //check if player not in form but still can't use weapon (broken/etc) + else if(!CanUseAttackType(attType)) //check if player not in form but still can't use (disarm case) { + //cannot use ranged/off attack, set values to 0 + if (attType != BASE_ATTACK) + { + min_damage=0; + max_damage=0; + return; + } weapon_mindamage = BASE_MINDAMAGE; weapon_maxdamage = BASE_MAXDAMAGE; } @@ -554,6 +619,24 @@ void Player::UpdateSpellCritChance(uint32 school) SetFloatValue(PLAYER_SPELL_CRIT_PERCENTAGE1 + school, crit); } +void Player::UpdateMeleeHitChances() +{ + m_modMeleeHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + m_modMeleeHitChance+= GetRatingBonusValue(CR_HIT_MELEE); +} + +void Player::UpdateRangedHitChances() +{ + m_modRangedHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_HIT_CHANCE); + m_modRangedHitChance+= GetRatingBonusValue(CR_HIT_RANGED); +} + +void Player::UpdateSpellHitChances() +{ + m_modSpellHitChance = GetTotalAuraModifier(SPELL_AURA_MOD_SPELL_HIT_CHANCE); + m_modSpellHitChance+= GetRatingBonusValue(CR_HIT_SPELL); +} + void Player::UpdateAllSpellCritChances() { for (int i = SPELL_SCHOOL_NORMAL; i < MAX_SPELL_SCHOOL; i++) @@ -574,10 +657,10 @@ void Player::UpdateExpertise(WeaponAttackType attack) { // item neutral spell if((*itr)->GetSpellProto()->EquippedItemClass == -1) - expertise += (*itr)->GetModifierValue(); + expertise += (*itr)->GetModifier()->m_amount; // item dependent spell else if(weapon && weapon->IsFitToSpellRequirements((*itr)->GetSpellProto())) - expertise += (*itr)->GetModifierValue(); + expertise += (*itr)->GetModifier()->m_amount; } if(expertise < 0) @@ -591,6 +674,12 @@ void Player::UpdateExpertise(WeaponAttackType attack) } } +void Player::ApplyManaRegenBonus(int32 amount, bool apply) +{ + m_baseManaRegen+= apply ? amount : -amount; + UpdateManaRegen(); +} + void Player::UpdateManaRegen() { float Intellect = GetStat(STAT_INTELLECT); @@ -600,14 +689,14 @@ void Player::UpdateManaRegen() power_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); // Mana regen from SPELL_AURA_MOD_POWER_REGEN aura - float power_regen_mp5 = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f; + float power_regen_mp5 = (GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) + m_baseManaRegen) / 5.0f; // Get bonus from SPELL_AURA_MOD_MANA_REGEN_FROM_STAT aura AuraList const& regenAura = GetAurasByType(SPELL_AURA_MOD_MANA_REGEN_FROM_STAT); for(AuraList::const_iterator i = regenAura.begin();i != regenAura.end(); ++i) { Modifier* mod = (*i)->GetModifier(); - power_regen_mp5 += GetStat(Stats(mod->m_miscvalue)) * (*i)->GetModifierValue() / 500.0f; + power_regen_mp5 += GetStat(Stats(mod->m_miscvalue)) * mod->m_amount / 500.0f; } // Bonus from some dummy auras @@ -624,9 +713,9 @@ void Player::UpdateManaRegen() int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); if (modManaRegenInterrupt > 100) modManaRegenInterrupt = 100; - SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f); + SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, power_regen_mp5 + power_regen * modManaRegenInterrupt / 100.0f); - SetStatFloatValue(PLAYER_FIELD_MOD_MANA_REGEN, power_regen_mp5 + power_regen); + SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, power_regen_mp5 + power_regen); } void Player::_ApplyAllStatBonuses() @@ -712,6 +801,27 @@ void Creature::UpdateMaxPower(Powers power) void Creature::UpdateAttackPowerAndDamage(bool ranged) { + UnitMods unitMod = ranged ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; + + uint16 index = UNIT_FIELD_ATTACK_POWER; + uint16 index_mod = UNIT_FIELD_ATTACK_POWER_MODS; + uint16 index_mult = UNIT_FIELD_ATTACK_POWER_MULTIPLIER; + + if(ranged) + { + index = UNIT_FIELD_RANGED_ATTACK_POWER; + index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS; + index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER; + } + + float base_attPower = GetModifierValue(unitMod, BASE_VALUE) * GetModifierValue(unitMod, BASE_PCT); + float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); + float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; + + SetInt32Value(index, (uint32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER field + SetInt32Value(index_mod, (uint32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field + SetFloatValue(index_mult, attPowerMultiplier); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field + //automatically update weapon damage after attack power modification if(ranged) UpdateDamagePhysical(RANGED_ATTACK); @@ -755,7 +865,7 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType) float total_value = GetModifierValue(unitMod, TOTAL_VALUE); float total_pct = GetModifierValue(unitMod, TOTAL_PCT); - if(attType == BASE_ATTACK && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED)) + if(!CanUseAttackType(attType)) { weapon_mindamage = 0; weapon_maxdamage = 0; @@ -923,7 +1033,7 @@ void Pet::UpdateAttackPowerAndDamage(bool ranged) if(getPetType() == HUNTER_PET) //hunter pets benefit from owner's attack power { bonusAP = owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.22f; - SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.125f)); + SetBonusDamage( int32(owner->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.1287f)); } //demons benefit from warlocks shadow or fire damage else if(getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK) @@ -954,9 +1064,9 @@ void Pet::UpdateAttackPowerAndDamage(bool ranged) float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; //UNIT_FIELD_(RANGED)_ATTACK_POWER field - SetUInt32Value(UNIT_FIELD_ATTACK_POWER, (uint32)base_attPower); + SetInt32Value(UNIT_FIELD_ATTACK_POWER, (int32)base_attPower); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MODS field - SetUInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (uint32)attPowerMod); + SetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS, (int32)attPowerMod); //UNIT_FIELD_(RANGED)_ATTACK_POWER_MULTIPLIER field SetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER, attPowerMultiplier); diff --git a/src/game/TargetedMovementGenerator.cpp b/src/game/TargetedMovementGenerator.cpp index 88558861257..d39c2c68071 100644 --- a/src/game/TargetedMovementGenerator.cpp +++ b/src/game/TargetedMovementGenerator.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/TargetedMovementGenerator.h b/src/game/TargetedMovementGenerator.h index 75e60728ea3..e6579c0b1de 100644 --- a/src/game/TargetedMovementGenerator.h +++ b/src/game/TargetedMovementGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/TaxiHandler.cpp b/src/game/TaxiHandler.cpp index 640618eaebb..743f09f94fc 100644 --- a/src/game/TaxiHandler.cpp +++ b/src/game/TaxiHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -56,7 +56,7 @@ void WorldSession::SendTaxiStatus( uint64 guid ) return; } - uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId()); + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer( )->GetTeam()); // not found nearest if(curloc == 0) @@ -71,7 +71,7 @@ void WorldSession::SendTaxiStatus( uint64 guid ) sLog.outDebug( "WORLD: Sent SMSG_TAXINODE_STATUS" ); } -void WorldSession::HandleTaxiQueryAvailableNodesOpcode( WorldPacket & recv_data ) +void WorldSession::HandleTaxiQueryAvailableNodes( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); @@ -103,7 +103,7 @@ void WorldSession::HandleTaxiQueryAvailableNodesOpcode( WorldPacket & recv_data void WorldSession::SendTaxiMenu( Creature* unit ) { // find current node - uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId()); + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer( )->GetTeam()); if ( curloc == 0 ) return; @@ -136,7 +136,7 @@ void WorldSession::SendDoFlight( uint16 MountId, uint32 path, uint32 pathNode ) bool WorldSession::SendLearnNewTaxiNode( Creature* unit ) { // find current node - uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId()); + uint32 curloc = objmgr.GetNearestTaxiNode(unit->GetPositionX(),unit->GetPositionY(),unit->GetPositionZ(),unit->GetMapId(),GetPlayer( )->GetTeam()); if ( curloc == 0 ) return true; // `true` send to avoid WorldSession::SendTaxiMenu call with one more curlock seartch with same false result. diff --git a/src/game/TemporarySummon.cpp b/src/game/TemporarySummon.cpp index 553f7644b64..788fe4d2b7d 100644 --- a/src/game/TemporarySummon.cpp +++ b/src/game/TemporarySummon.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/TemporarySummon.h b/src/game/TemporarySummon.h index 7f20ee9c5a9..c3441704438 100644 --- a/src/game/TemporarySummon.h +++ b/src/game/TemporarySummon.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index 3b4491b943e..8807dff64f8 100644 --- a/src/game/ThreatManager.cpp +++ b/src/game/ThreatManager.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -267,26 +267,36 @@ HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilRe { HostilReference* currentRef = NULL; bool found = false; + bool noPriorityTargetFound = false; std::list<HostilReference*>::iterator lastRef = iThreatList.end(); lastRef--; - for(std::list<HostilReference*>::iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found; ++iter) + for(std::list<HostilReference*>::iterator iter = iThreatList.begin(); iter != iThreatList.end() && !found;) { currentRef = (*iter); Unit* target = currentRef->getTarget(); assert(target); // if the ref has status online the target must be there ! - // some units are preferred in comparison to others - if(iter != lastRef && (target->IsImmunedToDamage(pAttacker->GetMeleeDamageSchoolMask(), false) || - target->hasUnitState(UNIT_STAT_CONFUSED) - ) ) + // some units are prefered in comparison to others + if(!noPriorityTargetFound && (target->IsImmunedToDamage(pAttacker->GetMeleeDamageSchoolMask()) || target->hasNegativeAuraWithInterruptFlag(AURA_INTERRUPT_FLAG_DAMAGE)) ) { - // current victim is a second choice target, so don't compare threat with it below - if(currentRef == pCurrentVictim) - pCurrentVictim = NULL; - continue; + if(iter != lastRef) + { + // current victim is a second choice target, so don't compare threat with it below + if(currentRef == pCurrentVictim) + pCurrentVictim = NULL; + ++iter; + continue; + } + else + { + // if we reached to this point, everyone in the threatlist is a second choice target. In such a situation the target with the highest threat should be attacked. + noPriorityTargetFound = true; + iter = iThreatList.begin(); + continue; + } } if(!pAttacker->IsOutOfThreatArea(target)) // skip non attackable currently targets @@ -314,6 +324,7 @@ HostilReference* ThreatContainer::selectNextVictim(Creature* pAttacker, HostilRe break; } } + ++iter; } if(!found) currentRef = NULL; diff --git a/src/game/ThreatManager.h b/src/game/ThreatManager.h index d4a3910e91e..2d81f411e78 100644 --- a/src/game/ThreatManager.h +++ b/src/game/ThreatManager.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -208,10 +208,10 @@ class TRINITY_DLL_SPEC ThreatManager // methods to access the lists from the outside to do sume dirty manipulation (scriping and such) // I hope they are used as little as possible. - inline std::list<HostilReference*>& getThreatList() { return iThreatContainer.getThreatList(); } - inline std::list<HostilReference*>& getOfflieThreatList() { return iThreatOfflineContainer.getThreatList(); } - inline ThreatContainer& getOnlineContainer() { return iThreatContainer; } - inline ThreatContainer& getOfflineContainer() { return iThreatOfflineContainer; } + std::list<HostilReference*>& getThreatList() { return iThreatContainer.getThreatList(); } + std::list<HostilReference*>& getOfflieThreatList() { return iThreatOfflineContainer.getThreatList(); } + ThreatContainer& getOnlineContainer() { return iThreatContainer; } + ThreatContainer& getOfflineContainer() { return iThreatOfflineContainer; } }; //================================================= diff --git a/src/game/TicketHandler.cpp b/src/game/TicketHandler.cpp index 5d6b1e095fa..8d6ed30687e 100644 --- a/src/game/TicketHandler.cpp +++ b/src/game/TicketHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS + * Copyright (C) 2005-2009 MaNGOS * - * Copyright (C) 2008 Trinity + * Copyright (C) 2008-2009 Trinity * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/TicketMgr.cpp b/src/game/TicketMgr.cpp index 09d975ccf21..a622a41aedc 100644 --- a/src/game/TicketMgr.cpp +++ b/src/game/TicketMgr.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS + * Copyright (C) 2005-2009 MaNGOS * - * Copyright (C) 2008 Trinity + * Copyright (C) 2008-2009 Trinity * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/TicketMgr.h b/src/game/TicketMgr.h index f8a0632c0ca..25d62462dc2 100644 --- a/src/game/TicketMgr.h +++ b/src/game/TicketMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS + * Copyright (C) 2005-2009 MaNGOS * - * Copyright (C) 2008 Trinity + * Copyright (C) 2008-2009 Trinity * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Tools.cpp b/src/game/Tools.cpp index 7abc016df48..f8663a4b4e4 100644 --- a/src/game/Tools.cpp +++ b/src/game/Tools.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Tools.h b/src/game/Tools.h index 03b48a7e9a3..887fe03045a 100644 --- a/src/game/Tools.h +++ b/src/game/Tools.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp index 2ac26f823d6..0178ed07fdf 100644 --- a/src/game/Totem.cpp +++ b/src/game/Totem.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -178,18 +178,18 @@ void Totem::SetTypeBySummonSpell(SpellEntry const * spellProto) m_type = TOTEM_STATUE; //Jewelery statue } -bool Totem::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) +bool Totem::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const { -/* for (int i=0;i<3;i++) + // TODO: possibly all negative auras immuned? + switch(spellInfo->EffectApplyAuraName[index]) { - switch(spellInfo->EffectApplyAuraName[i]) - { - case SPELL_AURA_PERIODIC_DAMAGE: - case SPELL_AURA_PERIODIC_LEECH: - return true; - default: - continue; - } - }*/ - return Creature::IsImmunedToSpell(spellInfo, useCharges); + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_MOD_FEAR: + case SPELL_AURA_TRANSFORM: + return true; + default: + break; + } + return Creature::IsImmunedToSpellEffect(spellInfo, index); } diff --git a/src/game/Totem.h b/src/game/Totem.h index 43ae4f4912c..572cfa6d315 100644 --- a/src/game/Totem.h +++ b/src/game/Totem.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -57,7 +57,7 @@ class Totem : public Creature void UpdateAttackPowerAndDamage(bool /*ranged*/ ) {} void UpdateDamagePhysical(WeaponAttackType /*attType*/) {} - bool IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges = false); + bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const; protected: TotemType m_type; diff --git a/src/game/TotemAI.cpp b/src/game/TotemAI.cpp index 4d7b45eba8e..81113a3a9f8 100644 --- a/src/game/TotemAI.cpp +++ b/src/game/TotemAI.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -82,21 +82,10 @@ TotemAI::UpdateAI(const uint32 /*diff*/) !victim->isTargetableForAttack() || !i_totem.IsWithinDistInMap(victim, max_range) || i_totem.IsFriendlyTo(victim) || !victim->isVisibleForOrDetect(&i_totem,false) ) { - CellPair p(Trinity::ComputeCellPair(i_totem.GetPositionX(),i_totem.GetPositionY())); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - victim = NULL; - Trinity::NearestAttackableUnitInObjectRangeCheck u_check(&i_totem, &i_totem, max_range); - Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck> checker(victim, u_check); - - TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); - TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); - - CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, grid_object_checker, *MapManager::Instance().GetMap(i_totem.GetMapId(), &i_totem)); - cell_lock->Visit(cell_lock, world_object_checker, *MapManager::Instance().GetMap(i_totem.GetMapId(), &i_totem)); + Trinity::UnitLastSearcher<Trinity::NearestAttackableUnitInObjectRangeCheck> checker(&i_totem, victim, u_check); + i_totem.VisitNearbyObject(max_range, checker); } // If have target diff --git a/src/game/TotemAI.h b/src/game/TotemAI.h index 8ce40e60c81..64675cd11e3 100644 --- a/src/game/TotemAI.h +++ b/src/game/TotemAI.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/TradeHandler.cpp b/src/game/TradeHandler.cpp index dc3bd020ccf..f444866e8aa 100644 --- a/src/game/TradeHandler.cpp +++ b/src/game/TradeHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index b2ed69fe251..f1d1ff412bf 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -139,7 +139,7 @@ void MapManager::LoadTransports() Transport::Transport() : GameObject() { // 2.3.2 - 0x5A - m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION); } bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags) @@ -147,6 +147,7 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, Relocate(x,y,z,ang); SetMapId(mapid); + // instance id and phaseMask isn't set to values different from std. if(!IsPositionValid()) { @@ -170,9 +171,10 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); - SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); - - SetUInt32Value(OBJECT_FIELD_ENTRY, goinfo->id); + //SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); + SetUInt32Value(GAMEOBJECT_FLAGS, MAKE_PAIR32(0x28, 0x64)); + SetUInt32Value(GAMEOBJECT_LEVEL, m_period); + SetEntry(goinfo->id); SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); @@ -181,7 +183,7 @@ bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, SetGoAnimProgress(animprogress); if(dynflags) - SetUInt32Value(GAMEOBJECT_DYN_FLAGS, dynflags); + SetUInt32Value(GAMEOBJECT_DYNAMIC, MAKE_PAIR32(0, dynflags)); return true; } @@ -479,11 +481,8 @@ bool Transport::AddPassenger(Player* passenger) bool Transport::RemovePassenger(Player* passenger) { - if (m_passengers.find(passenger) != m_passengers.end()) - { - sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), this->m_name.c_str()); - m_passengers.erase(passenger); - } + if (m_passengers.erase(passenger)) + sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), m_name.c_str()); return true; } diff --git a/src/game/Transports.h b/src/game/Transports.h index e49383ad1de..0cb6a6e7503 100644 --- a/src/game/Transports.h +++ b/src/game/Transports.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,16 +38,16 @@ class TransportPath uint32 delay; }; - inline void SetLength(const unsigned int sz) + void SetLength(const unsigned int sz) { i_nodes.resize( sz ); } - inline unsigned int Size(void) const { return i_nodes.size(); } - inline bool Empty(void) const { return i_nodes.empty(); } - inline void Resize(unsigned int sz) { i_nodes.resize(sz); } - inline void Clear(void) { i_nodes.clear(); } - inline PathNode* GetNodes(void) { return static_cast<PathNode *>(&i_nodes[0]); } + unsigned int Size(void) const { return i_nodes.size(); } + bool Empty(void) const { return i_nodes.empty(); } + void Resize(unsigned int sz) { i_nodes.resize(sz); } + void Clear(void) { i_nodes.clear(); } + PathNode* GetNodes(void) { return static_cast<PathNode *>(&i_nodes[0]); } PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } diff --git a/src/game/Traveller.h b/src/game/Traveller.h index 64b9d1c310d..6e7757d9bbf 100644 --- a/src/game/Traveller.h +++ b/src/game/Traveller.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -47,10 +47,10 @@ struct TRINITY_DLL_DECL Traveller operator T&(void) { return i_traveller; } operator const T&(void) { return i_traveller; } - inline float GetPositionX() const { return i_traveller.GetPositionX(); } - inline float GetPositionY() const { return i_traveller.GetPositionY(); } - inline float GetPositionZ() const { return i_traveller.GetPositionZ(); } - inline T& GetTraveller(void) { return i_traveller; } + float GetPositionX() const { return i_traveller.GetPositionX(); } + float GetPositionY() const { return i_traveller.GetPositionY(); } + float GetPositionZ() const { return i_traveller.GetPositionZ(); } + T& GetTraveller(void) { return i_traveller; } float Speed(void) { assert(false); return 0.0f; } void Relocation(float x, float y, float z, float orientation) {} diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 234922f040e..6996df9ed97 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -60,92 +60,17 @@ float baseMoveSpeed[MAX_MOVE_TYPE] = 3.141594f, // MOVE_TURN_RATE 7.0f, // MOVE_FLIGHT 4.5f, // MOVE_FLIGHT_BACK + 3.14f // MOVE_PITCH_RATE }; -void InitTriggerAuraData(); - -// auraTypes contains attacker auras capable of proc'ing cast auras -static Unit::AuraTypeSet GenerateAttakerProcCastAuraTypes() -{ - static Unit::AuraTypeSet auraTypes; - auraTypes.insert(SPELL_AURA_DUMMY); - auraTypes.insert(SPELL_AURA_PROC_TRIGGER_SPELL); - auraTypes.insert(SPELL_AURA_MOD_HASTE); - auraTypes.insert(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - return auraTypes; -} - -// auraTypes contains victim auras capable of proc'ing cast auras -static Unit::AuraTypeSet GenerateVictimProcCastAuraTypes() -{ - static Unit::AuraTypeSet auraTypes; - auraTypes.insert(SPELL_AURA_DUMMY); - auraTypes.insert(SPELL_AURA_PRAYER_OF_MENDING); - auraTypes.insert(SPELL_AURA_PROC_TRIGGER_SPELL); - return auraTypes; -} - -// auraTypes contains auras capable of proc effect/damage (but not cast) for attacker -static Unit::AuraTypeSet GenerateAttakerProcEffectAuraTypes() -{ - static Unit::AuraTypeSet auraTypes; - auraTypes.insert(SPELL_AURA_MOD_DAMAGE_DONE); - auraTypes.insert(SPELL_AURA_PROC_TRIGGER_DAMAGE); - auraTypes.insert(SPELL_AURA_MOD_CASTING_SPEED); - auraTypes.insert(SPELL_AURA_MOD_RATING); - return auraTypes; -} - -// auraTypes contains auras capable of proc effect/damage (but not cast) for victim -static Unit::AuraTypeSet GenerateVictimProcEffectAuraTypes() -{ - static Unit::AuraTypeSet auraTypes; - auraTypes.insert(SPELL_AURA_MOD_RESISTANCE); - auraTypes.insert(SPELL_AURA_PROC_TRIGGER_DAMAGE); - auraTypes.insert(SPELL_AURA_MOD_PARRY_PERCENT); - auraTypes.insert(SPELL_AURA_MOD_BLOCK_PERCENT); - auraTypes.insert(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); - return auraTypes; -} - -static Unit::AuraTypeSet attackerProcCastAuraTypes = GenerateAttakerProcCastAuraTypes(); -static Unit::AuraTypeSet attackerProcEffectAuraTypes = GenerateAttakerProcEffectAuraTypes(); - -static Unit::AuraTypeSet victimProcCastAuraTypes = GenerateVictimProcCastAuraTypes(); -static Unit::AuraTypeSet victimProcEffectAuraTypes = GenerateVictimProcEffectAuraTypes(); - -// auraTypes contains auras capable of proc'ing for attacker and victim -static Unit::AuraTypeSet GenerateProcAuraTypes() -{ - InitTriggerAuraData(); - - Unit::AuraTypeSet auraTypes; - auraTypes.insert(attackerProcCastAuraTypes.begin(),attackerProcCastAuraTypes.end()); - auraTypes.insert(attackerProcEffectAuraTypes.begin(),attackerProcEffectAuraTypes.end()); - auraTypes.insert(victimProcCastAuraTypes.begin(),victimProcCastAuraTypes.end()); - auraTypes.insert(victimProcEffectAuraTypes.begin(),victimProcEffectAuraTypes.end()); - return auraTypes; -} - -static Unit::AuraTypeSet procAuraTypes = GenerateProcAuraTypes(); - -bool IsPassiveStackableSpell( uint32 spellId ) -{ - if(!IsPassiveSpell(spellId)) - return false; - - SpellEntry const* spellProto = sSpellStore.LookupEntry(spellId); - if(!spellProto) - return false; - - for(int j = 0; j < 3; ++j) - { - if(std::find(procAuraTypes.begin(),procAuraTypes.end(),spellProto->EffectApplyAuraName[j])!=procAuraTypes.end()) - return false; - } - - return true; -} +// Used for prepare can/can`t triggr aura +static bool InitTriggerAuraData(); +// Define can trigger auras +static bool isTriggerAura[TOTAL_AURAS]; +// Define can`t trigger auras (need for disable second trigger) +static bool isNonTriggerAura[TOTAL_AURAS]; +// Prepare lists +static bool procPrepared = InitTriggerAuraData(); Unit::Unit() : WorldObject(), i_motionMaster(this), m_ThreatManager(this), m_HostilRefManager(this) @@ -154,7 +79,7 @@ Unit::Unit() m_objectType |= TYPEMASK_UNIT; m_objectTypeId = TYPEID_UNIT; // 2.3.2 - 0x70 - m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HASPOSITION); + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION); m_attackTimer[BASE_ATTACK] = 0; m_attackTimer[OFF_ATTACK] = 0; @@ -169,6 +94,7 @@ Unit::Unit() m_state = 0; m_form = FORM_NONE; m_deathState = ALIVE; + m_auraUpdateMask = 0; for (uint32 i = 0; i < CURRENT_MAX_SPELL; i++) m_currentSpells[i] = NULL; @@ -183,7 +109,6 @@ Unit::Unit() //m_AurasCheck = 2000; //m_removeAuraTimer = 4; //tmpAura = NULL; - waterbreath = false; m_Visibility = VISIBILITY_ON; @@ -283,6 +208,18 @@ void Unit::Update( uint32 p_time ) _UpdateAura(); }else m_AurasCheck -= p_time;*/ + const uint64& auramask = GetAuraUpdateMask(); + if (auramask) + { + for(uint32 i = 0; i < MAX_AURAS; ++i) + { + if(auramask & (uint64(1) << i)) + { + SendAuraUpdate(i); + } + } + ResetAuraUpdateMask(); + } // WARNING! Order of execution here is important, do not change. // Spells must be processed with event system BEFORE they go to _UpdateSpells. @@ -322,6 +259,7 @@ void Unit::Update( uint32 p_time ) ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, GetHealth() < GetMaxHealth()*0.20f); ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, GetHealth() < GetMaxHealth()*0.35f); + ModifyAuraState(AURA_STATE_HEALTH_ABOVE_75_PERCENT, GetHealth() > GetMaxHealth()*0.75f); i_motionMaster.UpdateMotion(p_time); } @@ -385,6 +323,11 @@ void Unit::SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 ty case 1: // stop packet SendMessageToSet( &data, true ); return; + case 2: // not used currently + data << float(0); // orientation + data << float(0); + data << float(0); + break; case 3: // not used currently data << uint64(0); // probably target guid break; @@ -738,6 +681,167 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa { DEBUG_LOG("DealDamage: victim just died"); Kill(pVictim, durabilityLoss); + + /*// find player: owner of controlled `this` or `this` itself maybe + Player *player = GetCharmerOrOwnerPlayerOrPlayerItself(); + + if(pVictim->GetTypeId() == TYPEID_UNIT && ((Creature*)pVictim)->GetLootRecipient()) + player = ((Creature*)pVictim)->GetLootRecipient(); + // Reward player, his pets, and group/raid members + // call kill spell proc event (before real die and combat stop to triggering auras removed at death/combat stop) + if(player && player!=pVictim) + { + player->RewardPlayerAndGroupAtKill(pVictim); + player->ProcDamageAndSpell(pVictim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_EX_NONE, 0); + } + + DEBUG_LOG("DealDamageAttackStop"); + + // stop combat + pVictim->CombatStop(); + pVictim->getHostilRefManager().deleteReferences(); + + bool damageFromSpiritOfRedemtionTalent = spellProto && spellProto->Id == 27795; + + // if talent known but not triggered (check priest class for speedup check) + Aura* spiritOfRedemtionTalentReady = NULL; + if( !damageFromSpiritOfRedemtionTalent && // not called from SPELL_AURA_SPIRIT_OF_REDEMPTION + pVictim->GetTypeId()==TYPEID_PLAYER && pVictim->getClass()==CLASS_PRIEST ) + { + AuraList const& vDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); + for(AuraList::const_iterator itr = vDummyAuras.begin(); itr != vDummyAuras.end(); ++itr) + { + if((*itr)->GetSpellProto()->SpellIconID==1654) + { + spiritOfRedemtionTalentReady = *itr; + break; + } + } + } + + DEBUG_LOG("SET JUST_DIED"); + if(!spiritOfRedemtionTalentReady) + pVictim->setDeathState(JUST_DIED); + + DEBUG_LOG("DealDamageHealth1"); + + if(spiritOfRedemtionTalentReady) + { + // save value before aura remove + uint32 ressSpellId = pVictim->GetUInt32Value(PLAYER_SELF_RES_SPELL); + if(!ressSpellId) + ressSpellId = ((Player*)pVictim)->GetResurrectionSpellId(); + + //Remove all expected to remove at death auras (most important negative case like DoT or periodic triggers) + pVictim->RemoveAllAurasOnDeath(); + + // restore for use at real death + pVictim->SetUInt32Value(PLAYER_SELF_RES_SPELL,ressSpellId); + + // FORM_SPIRITOFREDEMPTION and related auras + pVictim->CastSpell(pVictim,27827,true,NULL,spiritOfRedemtionTalentReady); + } + else + pVictim->SetHealth(0); + + // remember victim PvP death for corpse type and corpse reclaim delay + // at original death (not at SpiritOfRedemtionTalent timeout) + if( pVictim->GetTypeId()==TYPEID_PLAYER && !damageFromSpiritOfRedemtionTalent ) + ((Player*)pVictim)->SetPvPDeath(player!=NULL); + + // Call KilledUnit for creatures + if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->AI()) + ((Creature*)this)->AI()->KilledUnit(pVictim); + + // achievement stuff + if ( pVictim->GetTypeId() == TYPEID_PLAYER) + { + if(GetTypeId() == TYPEID_UNIT) + ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry()); + else if(GetTypeId() == TYPEID_PLAYER) + ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1); + } + + // 10% durability loss on death + // clean InHateListOf + if (pVictim->GetTypeId() == TYPEID_PLAYER) + { + // only if not player and not controlled by player pet. And not at BG + if (durabilityLoss && !player && !((Player*)pVictim)->InBattleGround()) + { + DEBUG_LOG("We are dead, loosing 10 percents durability"); + ((Player*)pVictim)->DurabilityLossAll(0.10f,false); + // durability lost message + WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 0); + ((Player*)pVictim)->GetSession()->SendPacket(&data); + } + } + else // creature died + { + DEBUG_LOG("DealDamageNotPlayer"); + Creature *cVictim = (Creature*)pVictim; + + if(!cVictim->isPet()) + { + cVictim->DeleteThreatList(); + cVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + // Call creature just died function + if (cVictim->AI()) + cVictim->AI()->JustDied(this); + + // Dungeon specific stuff, only applies to players killing creatures + if(cVictim->GetInstanceId()) + { + Map *m = cVictim->GetMap(); + Player *creditedPlayer = GetCharmerOrOwnerPlayerOrPlayerItself(); + // TODO: do instance binding anyway if the charmer/owner is offline + + if(m->IsDungeon() && creditedPlayer) + { + if(m->IsRaid() || m->IsHeroic()) + { + if(cVictim->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND) + ((InstanceMap *)m)->PermBindAllPlayers(creditedPlayer); + } + else + { + // the reset time is set but not added to the scheduler + // until the players leave the instance + time_t resettime = cVictim->GetRespawnTimeEx() + 2 * HOUR; + if(InstanceSave *save = sInstanceSaveManager.GetInstanceSave(cVictim->GetInstanceId())) + if(save->GetResetTime() < resettime) save->SetResetTime(resettime); + } + } + } + } + + // last damage from non duel opponent or opponent controlled creature + if(duel_hasEnded) + { + assert(pVictim->GetTypeId()==TYPEID_PLAYER); + Player *he = (Player*)pVictim; + + assert(he->duel); + + he->duel->opponent->CombatStopWithPets(true); + he->CombatStopWithPets(true); + + he->DuelComplete(DUEL_INTERUPTED); + } + + // battleground things (do this at the end, so the death state flag will be properly set to handle in the bg->handlekill) + if(pVictim->GetTypeId() == TYPEID_PLAYER && ((Player*)pVictim)->InBattleGround()) + { + Player *killed = ((Player*)pVictim); + if(BattleGround *bg = killed->GetBattleGround()) + if(player) + bg->HandleKillPlayer(killed, player); + //later we can add support for creature->player kills here i'm + //not sure, but i guess those kills also get counted in av + //else if(GetTypeId() == TYPEID_UNIT) + // bg->HandleKillPlayer(killed,(Creature*)this); + }*/ } else // if (health <= damage) { @@ -768,7 +872,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa //if (!spellProto || !(spellProto->AuraInterruptFlags&AURA_INTERRUPT_FLAG_DIRECT_DAMAGE)) pVictim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE, spellProto ? spellProto->Id : 0); } - if (pVictim->GetTypeId() != TYPEID_PLAYER) { if(spellProto && IsDamageToThreatSpell(spellProto)) @@ -835,7 +938,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if(spell->getState() == SPELL_STATE_PREPARING) { uint32 interruptFlags = spell->m_spellInfo->InterruptFlags; - if(interruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE) + if(interruptFlags & SPELL_INTERRUPT_FLAG_ABORT_ON_DMG) pVictim->InterruptNonMeleeSpells(false); else if(interruptFlags & SPELL_INTERRUPT_FLAG_PUSH_BACK) spell->Delayed(); @@ -1074,419 +1177,6 @@ void Unit::CastSpell(GameObject *go, uint32 spellId, bool triggered, Item *castI spell->prepare(&targets, triggeredByAura); } -/* -void Unit::DealFlatDamage(Unit *pVictim, SpellEntry const *spellInfo, uint32 *damage, CleanDamage *cleanDamage, bool *crit, bool isTriggeredSpell) -{ - // TODO this in only generic way, check for exceptions - DEBUG_LOG("DealFlatDamage (BEFORE) >> DMG:%u", *damage); - - // Per-damage class calculation - switch (spellInfo->DmgClass) - { - // Melee and Ranged Spells - case SPELL_DAMAGE_CLASS_RANGED: - case SPELL_DAMAGE_CLASS_MELEE: - { - // Calculate physical outcome - MeleeHitOutcome outcome = RollPhysicalOutcomeAgainst(pVictim, BASE_ATTACK, spellInfo); - - //Used to store the Hit Outcome - cleanDamage->hitOutCome = outcome; - - // Return miss/evade first (sends miss message) - switch(outcome) - { - case MELEE_HIT_EVADE: - { - SendAttackStateUpdate(HITINFO_MISS, pVictim, 1, GetSpellSchoolMask(spellInfo), 0, 0,0,VICTIMSTATE_EVADES,0); - *damage = 0; - return; - } - case MELEE_HIT_MISS: - { - SendAttackStateUpdate(HITINFO_MISS, pVictim, 1, GetSpellSchoolMask(spellInfo), 0, 0,0,VICTIMSTATE_NORMAL,0); - *damage = 0; - - if(GetTypeId()== TYPEID_PLAYER) - ((Player*)this)->UpdateWeaponSkill(BASE_ATTACK); - - CastMeleeProcDamageAndSpell(pVictim,0,GetSpellSchoolMask(spellInfo),BASE_ATTACK,MELEE_HIT_MISS,spellInfo,isTriggeredSpell); - return; - } - } - - // Hitinfo, Victimstate - uint32 hitInfo = HITINFO_NORMALSWING; - VictimState victimState = VICTIMSTATE_NORMAL; - - // Physical Damage - if ( GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_NORMAL ) - { - // apply spellmod to Done damage - if(Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_DAMAGE, *damage); - - //Calculate armor mitigation - uint32 damageAfterArmor = CalcArmorReducedDamage(pVictim, *damage); - - // random durability for main hand weapon (ABSORB) - if(damageAfterArmor < *damage) - if(pVictim->GetTypeId() == TYPEID_PLAYER) - if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_ABSORB))) - ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EquipmentSlots(urand(EQUIPMENT_SLOT_START,EQUIPMENT_SLOT_BACK))); - - cleanDamage->damage += *damage - damageAfterArmor; - *damage = damageAfterArmor; - } - // Magical Damage - else - { - // Calculate damage bonus - *damage = SpellDamageBonus(pVictim, spellInfo, *damage, SPELL_DIRECT_DAMAGE); - } - - // Classify outcome - switch (outcome) - { - case MELEE_HIT_BLOCK_CRIT: - case MELEE_HIT_CRIT: - { - uint32 bonusDmg = *damage; - - // Apply crit_damage bonus - if(Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRIT_DAMAGE_BONUS, bonusDmg); - - uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); - AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS); - for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i) - if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) - bonusDmg = uint32(bonusDmg * ((*i)->GetModifierValue()+100.0f)/100.0f); - - *damage += bonusDmg; - - // Resilience - reduce crit damage - if (pVictim->GetTypeId()==TYPEID_PLAYER) - { - uint32 resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(*damage); - cleanDamage->damage += resilienceReduction; - *damage -= resilienceReduction; - } - - *crit = true; - hitInfo |= HITINFO_CRITICALHIT; - - ModifyAuraState(AURA_STATE_CRIT, true); - StartReactiveTimer( REACTIVE_CRIT ); - - if(getClass()==CLASS_HUNTER) - { - ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, true); - StartReactiveTimer( REACTIVE_HUNTER_CRIT ); - } - - if ( outcome == MELEE_HIT_BLOCK_CRIT ) - { - uint32 blocked_amount = uint32(pVictim->GetShieldBlockValue()); - if (blocked_amount >= *damage) - { - hitInfo |= HITINFO_SWINGNOHITSOUND; - victimState = VICTIMSTATE_BLOCKS; - cleanDamage->damage += *damage; // To Help Calculate Rage - *damage = 0; - } - else - { - // To Help Calculate Rage - cleanDamage->damage += blocked_amount; - *damage = *damage - blocked_amount; - } - - pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); - pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - - if(pVictim->GetTypeId() == TYPEID_PLAYER) - { - // Update defense - ((Player*)pVictim)->UpdateDefense(); - - // random durability for main hand weapon (BLOCK) - if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK))) - ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND); - } - } - break; - } - case MELEE_HIT_PARRY: - { - cleanDamage->damage += *damage; // To Help Calculate Rage - *damage = 0; - victimState = VICTIMSTATE_PARRY; - - // Counter-attack ( explained in Unit::DoAttackDamage() ) - if(pVictim->GetTypeId()==TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_PARRY_HASTEN) ) - { - // Get attack timers - float offtime = float(pVictim->getAttackTimer(OFF_ATTACK)); - float basetime = float(pVictim->getAttackTimer(BASE_ATTACK)); - - // Reduce attack time - if (pVictim->haveOffhandWeapon() && offtime < basetime) - { - float percent20 = pVictim->GetAttackTime(OFF_ATTACK) * 0.20; - float percent60 = 3 * percent20; - if(offtime > percent20 && offtime <= percent60) - { - pVictim->setAttackTimer(OFF_ATTACK, uint32(percent20)); - } - else if(offtime > percent60) - { - offtime -= 2 * percent20; - pVictim->setAttackTimer(OFF_ATTACK, uint32(offtime)); - } - } - else - { - float percent20 = pVictim->GetAttackTime(BASE_ATTACK) * 0.20; - float percent60 = 3 * percent20; - if(basetime > percent20 && basetime <= percent60) - { - pVictim->setAttackTimer(BASE_ATTACK, uint32(percent20)); - } - else if(basetime > percent60) - { - basetime -= 2 * percent20; - pVictim->setAttackTimer(BASE_ATTACK, uint32(basetime)); - } - } - } - - if(pVictim->GetTypeId() == TYPEID_PLAYER) - { - // Update victim defense ? - ((Player*)pVictim)->UpdateDefense(); - - // random durability for main hand weapon (PARRY) - if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_PARRY))) - ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_MAINHAND); - } - - // Set parry flags - pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); - - // Mongoose bite - set only Counterattack here - if (pVictim->getClass() == CLASS_HUNTER) - { - pVictim->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true); - pVictim->StartReactiveTimer( REACTIVE_HUNTER_PARRY ); - } - else - { - pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); - pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - } - break; - } - case MELEE_HIT_DODGE: - { - if(pVictim->GetTypeId() == TYPEID_PLAYER) - ((Player*)pVictim)->UpdateDefense(); - - cleanDamage->damage += *damage; // To Help Calculate Rage - *damage = 0; - hitInfo |= HITINFO_SWINGNOHITSOUND; - victimState = VICTIMSTATE_DODGE; - - // Set dodge flags - pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); - - // Overpower - if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR) - { - ((Player*)this)->AddComboPoints(pVictim, 1); - StartReactiveTimer( REACTIVE_OVERPOWER ); - } - - // Riposte - if (pVictim->getClass() != CLASS_ROGUE) - { - pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); - pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - } - break; - } - case MELEE_HIT_BLOCK: - { - uint32 blocked_amount = uint32(pVictim->GetShieldBlockValue()); - if (blocked_amount >= *damage) - { - hitInfo |= HITINFO_SWINGNOHITSOUND; - victimState = VICTIMSTATE_BLOCKS; - cleanDamage->damage += *damage; // To Help Calculate Rage - *damage = 0; - } - else - { - // To Help Calculate Rage - cleanDamage->damage += blocked_amount; - *damage = *damage - blocked_amount; - } - - pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); - pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - - if(pVictim->GetTypeId() == TYPEID_PLAYER) - { - // Update defense - ((Player*)pVictim)->UpdateDefense(); - - // random durability for main hand weapon (BLOCK) - if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK))) - ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND); - } - break; - } - case MELEE_HIT_EVADE: // already processed early - case MELEE_HIT_MISS: // already processed early - case MELEE_HIT_GLANCING: - case MELEE_HIT_CRUSHING: - case MELEE_HIT_NORMAL: - break; - } - - // do all damage=0 cases here - if(*damage == 0) - CastMeleeProcDamageAndSpell(pVictim,0,GetSpellSchoolMask(spellInfo),BASE_ATTACK,outcome,spellInfo,isTriggeredSpell); - - break; - } - // Magical Attacks - case SPELL_DAMAGE_CLASS_NONE: - case SPELL_DAMAGE_CLASS_MAGIC: - { - // Calculate damage bonus - *damage = SpellDamageBonus(pVictim, spellInfo, *damage, SPELL_DIRECT_DAMAGE); - - *crit = isSpellCrit(pVictim, spellInfo, GetSpellSchoolMask(spellInfo), BASE_ATTACK); - if (*crit) - { - *damage = SpellCriticalBonus(spellInfo, *damage, pVictim); - - // Resilience - reduce crit damage - if (pVictim && pVictim->GetTypeId()==TYPEID_PLAYER) - { - uint32 damage_reduction = ((Player *)pVictim)->GetSpellCritDamageReduction(*damage); - if(*damage > damage_reduction) - *damage -= damage_reduction; - else - *damage = 0; - } - - cleanDamage->hitOutCome = MELEE_HIT_CRIT; - } - // spell proc all magic damage==0 case in this function - if(*damage == 0) - { - // Procflags - uint32 procAttacker = PROC_FLAG_HIT_SPELL; - uint32 procVictim = (PROC_FLAG_STRUCK_SPELL|PROC_FLAG_TAKE_DAMAGE); - - ProcDamageAndSpell(pVictim, procAttacker, procVictim, 0, GetSpellSchoolMask(spellInfo), spellInfo, isTriggeredSpell); - } - - break; - } - } - - // TODO this in only generic way, check for exceptions - DEBUG_LOG("DealFlatDamage (AFTER) >> DMG:%u", *damage); -} - -uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage, bool isTriggeredSpell, bool useSpellDamage) -{ - if(!this || !pVictim) - return 0; - if(!isAlive() || !pVictim->isAlive()) - return 0; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); - if(!spellInfo) - return 0; - - CleanDamage cleanDamage = CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL); - bool crit = false; - - if (useSpellDamage) - DealFlatDamage(pVictim, spellInfo, &damage, &cleanDamage, &crit, isTriggeredSpell); - - // If we actually dealt some damage (spell proc's for 0 damage (normal and magic) called in DealFlatDamage) - if(damage > 0) - { - // Calculate absorb & resists - uint32 absorb = 0; - uint32 resist = 0; - - CalcAbsorbResist(pVictim,GetSpellSchoolMask(spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); - - //No more damage left, target absorbed and/or resisted all damage - if (damage > absorb + resist) - damage -= absorb + resist; //Remove Absorbed and Resisted from damage actually dealt - else - { - uint32 HitInfo = HITINFO_SWINGNOHITSOUND; - - if (absorb) - HitInfo |= HITINFO_ABSORB; - if (resist) - { - HitInfo |= HITINFO_RESIST; - ProcDamageAndSpell(pVictim, PROC_FLAG_TARGET_RESISTS, PROC_FLAG_RESIST_SPELL, 0, GetSpellSchoolMask(spellInfo), spellInfo,isTriggeredSpell); - } - - //Send resist - SendAttackStateUpdate(HitInfo, pVictim, 1, GetSpellSchoolMask(spellInfo), damage, absorb,resist,VICTIMSTATE_NORMAL,0); - return 0; - } - - // Deal damage done - damage = DealDamage(pVictim, damage, &cleanDamage, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellInfo), spellInfo, true); - - // Send damage log - sLog.outDetail("SpellNonMeleeDamageLog: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u,absorb is %u,resist is %u", - GetGUIDLow(), GetTypeId(), pVictim->GetGUIDLow(), pVictim->GetTypeId(), damage, spellID, absorb,resist); - - // Actual log sent to client - SendSpellNonMeleeDamageLog(pVictim, spellID, damage + resist, GetSpellSchoolMask(spellInfo), absorb, resist, false, 0, crit); - - // Procflags - uint32 procAttacker = PROC_FLAG_HIT_SPELL; - uint32 procVictim = (PROC_FLAG_STRUCK_SPELL|PROC_FLAG_TAKE_DAMAGE); - - if (crit) - { - procAttacker |= PROC_FLAG_CRIT_SPELL; - procVictim |= PROC_FLAG_STRUCK_CRIT_SPELL; - } - - ProcDamageAndSpell(pVictim, procAttacker, procVictim, damage, GetSpellSchoolMask(spellInfo), spellInfo, isTriggeredSpell); - - return damage; - } - else - { - // all spell proc for 0 normal and magic damage called in DealFlatDamage - - //Check for rage - if(cleanDamage.damage) - // Rage from damage received. - if(pVictim->GetTypeId() == TYPEID_PLAYER && (pVictim->getPowerType() == POWER_RAGE)) - ((Player*)pVictim)->RewardRage(cleanDamage.damage, 0, false); - - return 0; - } -} -*/ - // Obsolete func need remove, here only for comotability vs another patches uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage, bool isTriggeredSpell, bool useSpellDamage) { @@ -1561,6 +1251,9 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 dama if (blocked) { damageInfo->blocked = uint32(pVictim->GetShieldBlockValue()); + //double blocked amount if block is critical + if (isBlockCritical()) + damageInfo->blocked+=damageInfo->blocked; if (damage < damageInfo->blocked) damageInfo->blocked = damage; damage-=damageInfo->blocked; @@ -1575,7 +1268,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 dama if (crit) { damageInfo->HitInfo|= SPELL_HIT_TYPE_CRIT; - damage = SpellCriticalBonus(spellInfo, damage, pVictim); + damage = SpellCriticalDamageBonus(spellInfo, damage, pVictim); // Resilience - reduce crit damage if (pVictim->GetTypeId()==TYPEID_PLAYER) damage -= ((Player*)pVictim)->GetSpellCritDamageReduction(damage); @@ -1585,12 +1278,12 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 dama } if( damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL ) - damage = CalcArmorReducedDamage(pVictim, damage); + damage = CalcArmorReducedDamage(pVictim, damage, spellInfo, attackType); // Calculate absorb resist if(damage > 0) { - CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist); + CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist, spellInfo); damage-= damageInfo->absorb + damageInfo->resist; } else @@ -1598,6 +1291,37 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 dama damageInfo->damage = damage; } +int32 Unit::GetIgnoredArmorMultiplier(SpellEntry const *spellInfo, WeaponAttackType attackType) +{ + if (GetTypeId() != TYPEID_PLAYER) + return 0; + //check if spell uses weapon + if (!spellInfo || spellInfo->EquippedItemClass!=ITEM_CLASS_WEAPON) + return 0; + Item *item = NULL; + if(attackType == BASE_ATTACK) + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); + else if (attackType == OFF_ATTACK) + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + else if (attackType == RANGED_ATTACK) + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED); + if (!item) + return 0; + + AuraList const& armAuras = GetAurasByType(SPELL_AURA_MOD_WEAPONTYPE_IGNORE_TARGET_RESISTANCE); + int32 armorIgnored = 0; + for(AuraList::const_iterator i = armAuras.begin();i != armAuras.end(); ++i) + { + if (!((*i)->GetSpellProto()->EquippedItemClass==item->GetProto()->Class + && (*i)->GetSpellProto()->EquippedItemSubClassMask & (1<<item->GetProto()->SubClass))) + continue; + + if((*i)->GetModifier()->m_amount) + armorIgnored += (*i)->GetModifier()->m_amount; + } + return (-armorIgnored); +} + void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss) { if (damageInfo==0) @@ -1627,20 +1351,6 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss) return; } - // update at damage Judgement aura duration that applied by attacker at victim - if(damageInfo->damage && spellProto->Id == 35395) - { - AuraMap& vAuras = pVictim->GetAuras(); - for(AuraMap::iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr) - { - SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); - if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID())) - { - (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration()); - (*itr).second->UpdateAuraDuration(); - } - } - } // Call default DealDamage CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, MELEE_HIT_NORMAL); DealDamage(pVictim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss); @@ -1694,7 +1404,7 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da } // Physical Immune check - if(damageInfo->target->IsImmunedToDamage(SpellSchoolMask(damageInfo->damageSchoolMask),true)) + if(damageInfo->target->IsImmunedToDamage(SpellSchoolMask(damageInfo->damageSchoolMask))) { damageInfo->HitInfo |= HITINFO_NORMALSWING; damageInfo->TargetState = VICTIMSTATE_IS_IMMUNE; @@ -1708,7 +1418,7 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da // Add melee damage bonus MeleeDamageBonus(damageInfo->target, &damage, damageInfo->attackType); // Calculate armor reduction - damageInfo->damage = CalcArmorReducedDamage(damageInfo->target, damage); + damageInfo->damage = CalcArmorReducedDamage(damageInfo->target, damage, NULL , damageInfo->attackType); damageInfo->cleanDamage += damage - damageInfo->damage; damageInfo->hitOutCome = RollMeleeOutcomeAgainst(damageInfo->target, damageInfo->attackType); @@ -1796,8 +1506,12 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da case MELEE_HIT_BLOCK: { damageInfo->TargetState = VICTIMSTATE_NORMAL; + damageInfo->HitInfo |= HITINFO_BLOCK; damageInfo->procEx|=PROC_EX_BLOCK; damageInfo->blocked_amount = damageInfo->target->GetShieldBlockValue(); + //double blocked amount if block is critical + if (isBlockCritical()) + damageInfo->blocked_amount+=damageInfo->blocked_amount; if (damageInfo->blocked_amount >= damageInfo->damage) { damageInfo->TargetState = VICTIMSTATE_BLOCKS; @@ -1943,28 +1657,13 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) CastSpell(pVictim, 1604, true); } - // update at damage Judgement aura duration that applied by attacker at victim - if(damageInfo->damage) - { - AuraMap& vAuras = pVictim->GetAuras(); - for(AuraMap::iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr) - { - SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); - if( spellInfo->AttributesEx3 & 0x40000 && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && ((*itr).second->GetCasterGUID() == GetGUID())) - { - (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration()); - (*itr).second->UpdateAuraDuration(); - } - } - } - // If not miss if (!(damageInfo->HitInfo & HITINFO_MISS)) { if(GetTypeId() == TYPEID_PLAYER && pVictim->isAlive()) { for(int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; i++) - ((Player*)this)->CastItemCombatSpell(((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0,i), pVictim, damageInfo->attackType); + ((Player*)this)->CastItemCombatSpell(((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0,i), pVictim, damageInfo->attackType); } // victim's damage shield @@ -1987,11 +1686,13 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) //CalcAbsorbResist(pVictim, SpellSchools(spellProto->School), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist); //damage-=absorb + resist; - WorldPacket data(SMSG_SPELLDAMAGESHIELD,(8+8+4+4)); + WorldPacket data(SMSG_SPELLDAMAGESHIELD,(8+8+4+4+4+4)); data << uint64(pVictim->GetGUID()); data << uint64(GetGUID()); + data << uint32(spellProto->Id); + data << uint32(damage); // Damage + data << uint32(0); // Overkill data << uint32(spellProto->SchoolMask); - data << uint32(damage); pVictim->SendMessageToSet(&data, true ); pVictim->DealDamage(this, damage, 0, SPELL_DIRECT_DAMAGE, GetSpellSchoolMask(spellProto), spellProto, true); @@ -2010,28 +1711,50 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) void Unit::HandleEmoteCommand(uint32 anim_id) { WorldPacket data( SMSG_EMOTE, 12 ); - data << anim_id << GetGUID(); - WPAssert(data.size() == 12); - + data << uint32(anim_id); + data << uint64(GetGUID()); SendMessageToSet(&data, true); } -uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage) +uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType) { uint32 newdamage = 0; float armor = pVictim->GetArmor(); // Ignore enemy armor by SPELL_AURA_MOD_TARGET_RESISTANCE aura armor += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, SPELL_SCHOOL_MASK_NORMAL); - if (armor<0.0f) armor=0.0f; + armor *= float((GetIgnoredArmorMultiplier(spellInfo, attackType)+100.0f)/100.0f); + if(spellInfo) + if(Player *modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_IGNORE_ARMOR, armor); - float tmpvalue = 0.0f; - if(getLevel() <= 59) //Level 1-59 - tmpvalue = armor / (armor + 400.0f + 85.0f * getLevel()); - else if(getLevel() < 70) //Level 60-69 - tmpvalue = armor / (armor - 22167.5f + 467.5f * getLevel()); - else //Level 70+ - tmpvalue = armor / (armor + 10557.5f); + AuraList const& ResIgnoreAurasAb = GetAurasByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST); + for(AuraList::const_iterator j = ResIgnoreAurasAb.begin();j != ResIgnoreAurasAb.end(); ++j) + { + if( (*j)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL + && (*j)->isAffectedOnSpell(spellInfo)) + armor= int32(float(armor) * (float(100-(*j)->GetModifier()->m_amount)/100.0f)); + } + + AuraList const& ResIgnoreAuras = GetAurasByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for(AuraList::const_iterator j = ResIgnoreAuras.begin();j != ResIgnoreAuras.end(); ++j) + { + if( (*j)->GetModifier()->m_miscvalue & SPELL_SCHOOL_MASK_NORMAL) + armor= int32(float(armor) * (float(100-(*j)->GetModifier()->m_amount)/100.0f)); + } + + // Apply Player CR_ARMOR_PENETRATION rating + if (GetTypeId()==TYPEID_PLAYER) + armor *= 1.0f - ((Player*)this)->GetRatingBonusValue(CR_ARMOR_PENETRATION) / 100.0f; + + if (armor < 0.0f) armor=0.0f; + + float levelModifier = getLevel(); + if ( levelModifier > 59 ) + levelModifier = levelModifier + (4.5f * (levelModifier-59)); + + float tmpvalue = 0.1f * armor / (8.5f * levelModifier + 40); + tmpvalue = tmpvalue/(1.0f + tmpvalue); if(tmpvalue < 0.0f) tmpvalue = 0.0f; @@ -2042,7 +1765,7 @@ uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage) return (newdamage > 1) ? newdamage : 1; } -void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist) +void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist, SpellEntry const *spellInfo) { if(!pVictim || !pVictim->isAlive() || !damage) return; @@ -2078,95 +1801,272 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe *resist += uint32(damage * m / 4); if(*resist > damage) *resist = damage; + + AuraList const& ResIgnoreAurasAb = GetAurasByType(SPELL_AURA_MOD_ABILITY_IGNORE_TARGET_RESIST); + for(AuraList::const_iterator j = ResIgnoreAurasAb.begin();j != ResIgnoreAurasAb.end(); ++j) + { + if( (*j)->GetModifier()->m_miscvalue & schoolMask + && (*j)->isAffectedOnSpell(spellInfo)) + *resist= int32(float(*resist) * (float(100-(*j)->GetModifier()->m_amount)/100.0f)); + } + + AuraList const& ResIgnoreAuras = GetAurasByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for(AuraList::const_iterator j = ResIgnoreAuras.begin();j != ResIgnoreAuras.end(); ++j) + { + if( (*j)->GetModifier()->m_miscvalue & schoolMask) + *resist= int32(float(*resist) * (float(100-(*j)->GetModifier()->m_amount)/100.0f)); + } } else *resist = 0; int32 RemainingDamage = damage - *resist; + // Get unit state (need for some absorb check) + uint32 unitflag = pVictim->GetUInt32Value(UNIT_FIELD_FLAGS); + // Reflect damage spells (not cast any damage spell in aura lookup) + uint32 reflectSpell = 0; + int32 reflectDamage = 0; + // Need remove expired auras after + bool existExpired = false; // absorb without mana cost - int32 reflectDamage = 0; - Aura* reflectAura = NULL; AuraList const& vSchoolAbsorb = pVictim->GetAurasByType(SPELL_AURA_SCHOOL_ABSORB); - for(AuraList::const_iterator i = vSchoolAbsorb.begin(), next; i != vSchoolAbsorb.end() && RemainingDamage > 0; i = next) + for(AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end() && RemainingDamage > 0; ++i) { - next = i; ++next; - - if (((*i)->GetModifier()->m_miscvalue & schoolMask)==0) + Modifier* mod = (*i)->GetModifier(); + if (!(mod->m_miscvalue & schoolMask)) continue; - // Cheat Death - if((*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && (*i)->GetSpellProto()->SpellIconID == 2109) + SpellEntry const* spellProto = (*i)->GetSpellProto(); + + // Max Amount can be absorbed by this aura + int32 currentAbsorb = mod->m_amount; + + // Found empty aura (umpossible but..) + if (currentAbsorb <=0) { - if (((Player*)pVictim)->HasSpellCooldown(31231)) - continue; - if (pVictim->GetHealth() <= RemainingDamage) + existExpired = true; + continue; + } + // Handle custom absorb auras + // TODO: try find better way + switch(spellProto->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: { - int32 chance = (*i)->GetModifier()->m_amount; - if (roll_chance_i(chance)) + // Astral Shift + if (spellProto->SpellIconID == 3066) { - pVictim->CastSpell(pVictim,31231,true); - ((Player*)pVictim)->AddSpellCooldown(31231,0,time(NULL)+60); - - // with health > 10% lost health until health==10%, in other case no losses - uint32 health10 = pVictim->GetMaxHealth()/10; - RemainingDamage = pVictim->GetHealth() > health10 ? pVictim->GetHealth() - health10 : 0; + //reduces all damage taken while stun, fear or silence + if (unitflag & (UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED)) + RemainingDamage -= RemainingDamage * currentAbsorb / 100; + continue; } + // Nerves of Steel + if (spellProto->SpellIconID == 2115) + { + // while affected by Stun and Fear + if (unitflag&(UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING)) + RemainingDamage -= RemainingDamage * currentAbsorb / 100; + continue; + } + // Spell Deflection + if (spellProto->SpellIconID == 3006) + { + // You have a chance equal to your Parry chance + if (damagetype == DIRECT_DAMAGE && // Only for direct damage + roll_chance_f(pVictim->GetUnitParryChance())) // Roll chance + RemainingDamage -= RemainingDamage * currentAbsorb / 100; + continue; + } + // Reflective Shield (Lady Malande boss) + if (spellProto->Id == 41475) + { + if(RemainingDamage < currentAbsorb) + reflectDamage = RemainingDamage / 2; + else + reflectDamage = currentAbsorb / 2; + reflectSpell = 33619; + break; + } + if (spellProto->Id == 39228 || // Argussian Compass + spellProto->Id == 60218) // Essence of Gossamer + { + // Max absorb stored in 1 dummy effect + if (spellProto->EffectBasePoints[1] < currentAbsorb) + currentAbsorb = spellProto->EffectBasePoints[1]; + break; + } + break; } - continue; - } - - int32 currentAbsorb; - - //Reflective Shield - if ((pVictim != this) && (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_PRIEST && (*i)->GetSpellProto()->SpellFamilyFlags == 0x1) - { - if(Unit* caster = (*i)->GetCaster()) + case SPELLFAMILY_DRUID: + { + // Primal Tenacity + if (spellProto->SpellIconID == 2253) + { + //reduces all damage taken while Stunned + if (unitflag & UNIT_FLAG_STUNNED) + RemainingDamage -= RemainingDamage * currentAbsorb / 100; + continue; + } + break; + } + case SPELLFAMILY_ROGUE: { - AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(AuraList::const_iterator k = vOverRideCS.begin(); k != vOverRideCS.end(); ++k) + // Cheat Death + if(spellProto->SpellIconID == 2109) { - switch((*k)->GetModifier()->m_miscvalue) + if (pVictim->GetTypeId()==TYPEID_PLAYER && // Only players + pVictim->GetHealth() <= RemainingDamage && // Only if damage kill + !((Player*)pVictim)->HasSpellCooldown(31231) && // Only if no cooldown + roll_chance_i(currentAbsorb)) // Only if roll { - case 5065: // Rank 1 - case 5064: // Rank 2 - case 5063: // Rank 3 - case 5062: // Rank 4 - case 5061: // Rank 5 - { - if(RemainingDamage >= (*i)->GetModifier()->m_amount) - reflectDamage = (*i)->GetModifier()->m_amount * (*k)->GetModifier()->m_amount/100; - else - reflectDamage = (*k)->GetModifier()->m_amount * RemainingDamage/100; - reflectAura = *i; - - } break; - default: break; + pVictim->CastSpell(pVictim,31231,true); + ((Player*)pVictim)->AddSpellCooldown(31231,0,time(NULL)+60); + // with health > 10% lost health until health==10%, in other case no losses + uint32 health10 = pVictim->GetMaxHealth()/10; + RemainingDamage = pVictim->GetHealth() > health10 ? pVictim->GetHealth() - health10 : 0; } - - if(reflectDamage) + continue; + } + break; + } + case SPELLFAMILY_PRIEST: + { + // Reflective Shield + if (spellProto->SpellFamilyFlags == 0x1) + { + if (pVictim == this) break; + Unit* caster = (*i)->GetCaster(); + if (!caster) + break; + int32 reflectDamage = 0; + AuraList const& vOverRideCS = caster->GetAurasByType(SPELL_AURA_DUMMY); + for(AuraList::const_iterator k = vOverRideCS.begin(); k != vOverRideCS.end(); ++k) + { + switch((*k)->GetModifier()->m_miscvalue) + { + case 5065: // Rank 1 + case 5064: // Rank 2 + case 5063: // Rank 3 + { + if(RemainingDamage >= currentAbsorb) + reflectDamage = (*k)->GetModifier()->m_amount * currentAbsorb/100; + else + reflectDamage = (*k)->GetModifier()->m_amount * RemainingDamage/100; + reflectSpell = 33619; + } break; + default: break; + } + } + break; + } + break; + } + case SPELLFAMILY_SHAMAN: + { + // Astral Shift + if (spellProto->SpellIconID == 3066) + { + //reduces all damage taken while stun, fear or silence + if (unitflag & (UNIT_FLAG_STUNNED|UNIT_FLAG_FLEEING|UNIT_FLAG_SILENCED)) + RemainingDamage -= RemainingDamage * currentAbsorb / 100; + continue; + } + break; + } + case SPELLFAMILY_DEATHKNIGHT: + { + // Shadow of Death + if (spellProto->SpellIconID == 1958) + { + // TODO: absorb only while transform + continue; + } + // Anti-Magic Shell (on self) + if (spellProto->Id == 48707) + { + // damage absorbed by Anti-Magic Shell energizes the DK with additional runic power. + // This, if I'm not mistaken, shows that we get back ~2% of the absorbed damage as runic power. + int32 absorbed = RemainingDamage * currentAbsorb / 100; + int32 regen = absorbed * 2 / 10; + pVictim->CastCustomSpell(pVictim, 49088, ®en, 0, 0, true, 0, *i); + RemainingDamage -= absorbed; + continue; + } + // Anti-Magic Shell (on single party/raid member) + if (spellProto->Id == 50462) + { + RemainingDamage -= RemainingDamage * currentAbsorb / 100; + continue; + } + // Anti-Magic Zone + if (spellProto->Id == 50461) + { + Unit* caster = (*i)->GetCaster(); + if (!caster) + continue; + int32 absorbed = RemainingDamage * currentAbsorb / 100; + int32 canabsorb = caster->GetHealth(); + if (canabsorb < absorbed) + absorbed = canabsorb; + DealDamage(caster, absorbed, NULL, damagetype, schoolMask, 0, false); + RemainingDamage -= absorbed; + continue; } + break; } + default: + break; } - if (RemainingDamage >= (*i)->GetModifier()->m_amount) + // currentAbsorb - damage can be absorbed by shield + // If need absorb less damage + if (RemainingDamage < currentAbsorb) + currentAbsorb = RemainingDamage; + + AuraList const& AbsIgnoreAurasAb = GetAurasByType(SPELL_AURA_MOD_TARGET_ABILITY_ABSORB_SCHOOL); + for(AuraList::const_iterator j = AbsIgnoreAurasAb.begin();j != AbsIgnoreAurasAb.end(); ++j) { - currentAbsorb = (*i)->GetModifier()->m_amount; - pVictim->RemoveAurasDueToSpell((*i)->GetId()); - next = vSchoolAbsorb.begin(); + if( (*j)->GetModifier()->m_miscvalue & (*i)->GetModifier()->m_miscvalue + && (*j)->isAffectedOnSpell(spellInfo)) + currentAbsorb= int32(float(currentAbsorb) * (float(100-(*j)->GetModifier()->m_amount)/100.0f)); } - else + + AuraList const& AbsIgnoreAuras = GetAurasByType(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL); + for(AuraList::const_iterator j = AbsIgnoreAuras.begin();j != AbsIgnoreAuras.end(); ++j) { - currentAbsorb = RemainingDamage; - (*i)->GetModifier()->m_amount -= RemainingDamage; + if( (*j)->GetModifier()->m_miscvalue & (*i)->GetModifier()->m_miscvalue) + currentAbsorb= int32(float(currentAbsorb) * (float(100-(*j)->GetModifier()->m_amount)/100.0f)); } RemainingDamage -= currentAbsorb; + + // Reduce shield amount + mod->m_amount-=currentAbsorb; + // Need remove it later + if (mod->m_amount<=0) + existExpired = true; + } + + // Remove all expired absorb auras + if (existExpired) + { + for(AuraList::const_iterator i = vSchoolAbsorb.begin(); i != vSchoolAbsorb.end();) + { + if ((*i)->GetModifier()->m_amount<=0) + { + pVictim->RemoveAurasDueToSpell((*i)->GetId()); + i = vSchoolAbsorb.begin(); + } + else + ++i; + } } - // do not cast spells while looping auras; auras can get invalid otherwise - if (reflectDamage) - pVictim->CastCustomSpell(this, 33619, &reflectDamage, NULL, NULL, true, NULL, reflectAura); + // Cast back reflect damage spell + if (reflectSpell) + pVictim->CastCustomSpell(this, reflectSpell, &reflectDamage, NULL, NULL, true); // absorb by mana cost AuraList const& vManaShield = pVictim->GetAurasByType(SPELL_AURA_MANA_SHIELD); @@ -2185,7 +2085,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe currentAbsorb = RemainingDamage; float manaMultiplier = (*i)->GetSpellProto()->EffectMultipleValue[(*i)->GetEffIndex()]; - if(Player *modOwner = GetSpellModOwner()) + if(Player *modOwner = pVictim->GetSpellModOwner()) modOwner->ApplySpellMod((*i)->GetId(), SPELLMOD_MULTIPLE_VALUE, manaMultiplier); int32 maxAbsorb = int32(pVictim->GetPower(POWER_MANA) / manaMultiplier); @@ -2264,407 +2164,6 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe *absorb = damage - RemainingDamage - *resist; } -/* -void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDamage, uint32 *blocked_amount, SpellSchoolMask damageSchoolMask, uint32 *hitInfo, VictimState *victimState, uint32 *absorbDamage, uint32 *resistDamage, WeaponAttackType attType, SpellEntry const *spellCasted, bool isTriggeredSpell) -{ - MeleeHitOutcome outcome; - - // If is casted Melee spell, calculate like physical - if(!spellCasted) - outcome = RollMeleeOutcomeAgainst (pVictim, attType); - else - outcome = RollPhysicalOutcomeAgainst (pVictim, attType, spellCasted); - - if(outcome == MELEE_HIT_MISS ||outcome == MELEE_HIT_DODGE ||outcome == MELEE_HIT_BLOCK ||outcome == MELEE_HIT_PARRY) - pVictim->AddThreat(this, 0.0f); - switch(outcome) - { - case MELEE_HIT_EVADE: - { - *hitInfo |= HITINFO_MISS; - *damage = 0; - cleanDamage->damage = 0; - return; - } - case MELEE_HIT_MISS: - { - *hitInfo |= HITINFO_MISS; - *damage = 0; - cleanDamage->damage = 0; - if(GetTypeId()== TYPEID_PLAYER) - ((Player*)this)->UpdateWeaponSkill(attType); - return; - } - } - - /// If this is a creature and it attacks from behind it has a probability to daze it's victim - if( (outcome==MELEE_HIT_CRIT || outcome==MELEE_HIT_CRUSHING || outcome==MELEE_HIT_NORMAL || outcome==MELEE_HIT_GLANCING) && - GetTypeId() != TYPEID_PLAYER && !((Creature*)this)->GetCharmerOrOwnerGUID() && !pVictim->HasInArc(M_PI, this) - && pVictim->GetTypeId() == TYPEID_PLAYER) - { - // -probability is between 0% and 40% - // 20% base chance - float Probability = 20; - - //there is a newbie protection, at level 10 just 7% base chance; assuming linear function - if( pVictim->getLevel() < 30 ) - Probability = 0.65f*pVictim->getLevel()+0.5; - - uint32 VictimDefense=pVictim->GetDefenseSkillValue(this); - uint32 AttackerMeleeSkill=GetUnitMeleeSkill(pVictim); - - Probability *= AttackerMeleeSkill/(float)VictimDefense; - - if(Probability > 40.0f) - Probability = 40.0f; - - if(roll_chance_f(Probability)) - CastSpell(pVictim, 1604, true); - } - - //Calculate the damage after armor mitigation if SPELL_SCHOOL_NORMAL - if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL) - { - uint32 damageAfterArmor = CalcArmorReducedDamage(pVictim, *damage); - - // random durability for main hand weapon (ABSORB) - if(damageAfterArmor < *damage) - if(pVictim->GetTypeId() == TYPEID_PLAYER) - if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_ABSORB))) - ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EquipmentSlots(urand(EQUIPMENT_SLOT_START,EQUIPMENT_SLOT_BACK))); - - cleanDamage->damage += *damage - damageAfterArmor; - *damage = damageAfterArmor; - } - - if(GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() != CREATURE_TYPE_CRITTER ) - ((Player*)this)->UpdateCombatSkills(pVictim, attType, outcome, false); - - if(GetTypeId() != TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER) - ((Player*)pVictim)->UpdateCombatSkills(this, attType, outcome, true); - - switch (outcome) - { - case MELEE_HIT_BLOCK_CRIT: - case MELEE_HIT_CRIT: - { - //*hitInfo = 0xEA; - // 0xEA - *hitInfo = HITINFO_CRITICALHIT | HITINFO_NORMALSWING2 | 0x8; - - // Crit bonus calc - uint32 crit_bonus; - crit_bonus = *damage; - - // Apply crit_damage bonus for melee spells - if (spellCasted) - { - if(Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellCasted->Id, SPELLMOD_CRIT_DAMAGE_BONUS, crit_bonus); - - uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); - AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS); - for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i) - if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) - crit_bonus = uint32(crit_bonus * ((*i)->GetModifierValue()+100.0f)/100.0f); - } - - *damage += crit_bonus; - - uint32 resilienceReduction = 0; - - if(attType == RANGED_ATTACK) - { - int32 mod = pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE); - *damage = int32((*damage) * float((100.0f + mod)/100.0f)); - // Resilience - reduce crit damage - if (pVictim->GetTypeId()==TYPEID_PLAYER) - resilienceReduction = ((Player*)pVictim)->GetRangedCritDamageReduction(*damage); - } - else - { - int32 mod = pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE); - mod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE); - *damage = int32((*damage) * float((100.0f + mod)/100.0f)); - // Resilience - reduce crit damage - if (pVictim->GetTypeId()==TYPEID_PLAYER) - resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(*damage); - } - - *damage -= resilienceReduction; - cleanDamage->damage += resilienceReduction; - - if(GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() != TYPEID_PLAYER && pVictim->GetCreatureType() != CREATURE_TYPE_CRITTER ) - ((Player*)this)->UpdateWeaponSkill(attType); - - ModifyAuraState(AURA_STATE_CRIT, true); - StartReactiveTimer( REACTIVE_CRIT ); - - if(getClass()==CLASS_HUNTER) - { - ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, true); - StartReactiveTimer( REACTIVE_HUNTER_CRIT ); - } - - if ( outcome == MELEE_HIT_BLOCK_CRIT ) - { - *blocked_amount = pVictim->GetShieldBlockValue(); - - if (pVictim->GetUnitBlockChance()) - pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYSHIELD); - else - pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); - - //Only set VICTIMSTATE_BLOCK on a full block - if (*blocked_amount >= uint32(*damage)) - { - *victimState = VICTIMSTATE_BLOCKS; - *blocked_amount = uint32(*damage); - } - - if(pVictim->GetTypeId() == TYPEID_PLAYER) - { - // Update defense - ((Player*)pVictim)->UpdateDefense(); - - // random durability for main hand weapon (BLOCK) - if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK))) - ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND); - } - - pVictim->ModifyAuraState(AURA_STATE_DEFENSE,true); - pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - break; - } - - pVictim->HandleEmoteCommand(EMOTE_ONESHOT_WOUNDCRITICAL); - break; - } - case MELEE_HIT_PARRY: - { - if(attType == RANGED_ATTACK) //range attack - no parry - { - outcome = MELEE_HIT_NORMAL; - break; - } - - cleanDamage->damage += *damage; - *damage = 0; - *victimState = VICTIMSTATE_PARRY; - - // instant (maybe with small delay) counter attack - { - float offtime = float(pVictim->getAttackTimer(OFF_ATTACK)); - float basetime = float(pVictim->getAttackTimer(BASE_ATTACK)); - - // after parry nearest next attack time will reduced at %40 from full attack time. - // The delay cannot be reduced to less than 20% of your weapon base swing delay. - if (pVictim->haveOffhandWeapon() && offtime < basetime) - { - float percent20 = pVictim->GetAttackTime(OFF_ATTACK)*0.20; - float percent60 = 3*percent20; - // set to 20% if in range 20%...20+40% of full time - if(offtime > percent20 && offtime <= percent60) - { - pVictim->setAttackTimer(OFF_ATTACK,uint32(percent20)); - } - // decrease at %40 from full time - else if(offtime > percent60) - { - offtime -= 2*percent20; - pVictim->setAttackTimer(OFF_ATTACK,uint32(offtime)); - } - // ELSE not changed - } - else - { - float percent20 = pVictim->GetAttackTime(BASE_ATTACK)*0.20; - float percent60 = 3*percent20; - // set to 20% if in range 20%...20+40% of full time - if(basetime > percent20 && basetime <= percent60) - { - pVictim->setAttackTimer(BASE_ATTACK,uint32(percent20)); - } - // decrease at %40 from full time - else if(basetime > percent60) - { - basetime -= 2*percent20; - pVictim->setAttackTimer(BASE_ATTACK,uint32(basetime)); - } - // ELSE not changed - } - } - - if(pVictim->GetTypeId() == TYPEID_PLAYER) - { - // Update victim defense ? - ((Player*)pVictim)->UpdateDefense(); - - // random durability for main hand weapon (PARRY) - if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_PARRY))) - ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_MAINHAND); - } - - pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); - - if (pVictim->getClass() == CLASS_HUNTER) - { - pVictim->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true); - pVictim->StartReactiveTimer( REACTIVE_HUNTER_PARRY ); - } - else - { - pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); - pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - } - - CastMeleeProcDamageAndSpell(pVictim, 0, damageSchoolMask, attType, outcome, spellCasted, isTriggeredSpell); - return; - } - case MELEE_HIT_DODGE: - { - if(attType == RANGED_ATTACK) //range attack - no dodge - { - outcome = MELEE_HIT_NORMAL; - break; - } - - cleanDamage->damage += *damage; - *damage = 0; - *victimState = VICTIMSTATE_DODGE; - - if(pVictim->GetTypeId() == TYPEID_PLAYER) - ((Player*)pVictim)->UpdateDefense(); - - pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); - - if (pVictim->getClass() != CLASS_ROGUE) // Riposte - { - pVictim->ModifyAuraState(AURA_STATE_DEFENSE, true); - pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - } - - // Overpower - if (GetTypeId() == TYPEID_PLAYER && getClass() == CLASS_WARRIOR) - { - ((Player*)this)->AddComboPoints(pVictim, 1); - StartReactiveTimer( REACTIVE_OVERPOWER ); - } - - CastMeleeProcDamageAndSpell(pVictim, 0, damageSchoolMask, attType, outcome, spellCasted, isTriggeredSpell); - return; - } - case MELEE_HIT_BLOCK: - { - *blocked_amount = pVictim->GetShieldBlockValue(); - - if (pVictim->GetUnitBlockChance()) - pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYSHIELD); - else - pVictim->HandleEmoteCommand(EMOTE_ONESHOT_PARRYUNARMED); - - //Only set VICTIMSTATE_BLOCK on a full block - if (*blocked_amount >= uint32(*damage)) - { - *victimState = VICTIMSTATE_BLOCKS; - *blocked_amount = uint32(*damage); - } - - if(pVictim->GetTypeId() == TYPEID_PLAYER) - { - // Update defense - ((Player*)pVictim)->UpdateDefense(); - - // random durability for main hand weapon (BLOCK) - if (roll_chance_f(sWorld.getRate(RATE_DURABILITY_LOSS_BLOCK))) - ((Player*)pVictim)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_OFFHAND); - } - - pVictim->ModifyAuraState(AURA_STATE_DEFENSE,true); - pVictim->StartReactiveTimer( REACTIVE_DEFENSE ); - - break; - } - case MELEE_HIT_GLANCING: - { - int32 leveldif = int32(pVictim->getLevel()) - int32(getLevel()); - if (leveldif > 3) leveldif = 3; - *damage *= (1 - leveldif * 0.1f); - cleanDamage->damage = *damage; - *hitInfo |= HITINFO_GLANCING; - break; - } - case MELEE_HIT_CRUSHING: - { - // 150% normal damage - *damage += (*damage / 2); - cleanDamage->damage = *damage; - *hitInfo |= HITINFO_CRUSHING; - // TODO: victimState, victim animation? - break; - } - default: - break; - } - - // apply melee damage bonus and absorb only if base damage not fully blocked to prevent negative damage or damage with full block - if(*victimState != VICTIMSTATE_BLOCKS) - { - MeleeDamageBonus(pVictim, damage,attType,spellCasted); - CalcAbsorbResist(pVictim, damageSchoolMask, DIRECT_DAMAGE, *damage-*blocked_amount, absorbDamage, resistDamage); - } - - if (*absorbDamage) *hitInfo |= HITINFO_ABSORB; - if (*resistDamage) *hitInfo |= HITINFO_RESIST; - - cleanDamage->damage += *blocked_amount; - - if (*damage <= *absorbDamage + *resistDamage + *blocked_amount) - { - //*hitInfo = 0x00010020; - //*hitInfo |= HITINFO_SWINGNOHITSOUND; - //*damageType = 0; - CastMeleeProcDamageAndSpell(pVictim, 0, damageSchoolMask, attType, outcome, spellCasted, isTriggeredSpell); - return; - } - - // update at damage Judgement aura duration that applied by attacker at victim - if(*damage) - { - AuraMap const& vAuras = pVictim->GetAuras(); - for(AuraMap::const_iterator itr = vAuras.begin(); itr != vAuras.end(); ++itr) - { - SpellEntry const *spellInfo = (*itr).second->GetSpellProto(); - if( (spellInfo->AttributesEx3 & 0x40000) && spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN && - ((*itr).second->GetCasterGUID() == GetGUID() && (!spellCasted || spellCasted->Id == 35395)) ) - { - (*itr).second->SetAuraDuration((*itr).second->GetAuraMaxDuration()); - (*itr).second->UpdateAuraDuration(); - } - } - } - - CastMeleeProcDamageAndSpell(pVictim, (*damage - *absorbDamage pVictim->SpellNonMeleeDamageLog(this, (*i)->GetId(), (*i)->GetModifier()->m_amount, false, false);eld - // yet another hack to fix crashes related to the aura getting removed during iteration - std::set<Aura*> alreadyDone; - uint32 removedAuras = pVictim->m_removedAuras; - AuraList const& vDamageShields = pVictim->GetAurasByType(SPELL_AURA_DAMAGE_SHIELD); - for(AuraList::const_iterator i = vDamageShields.begin(), next = vDamageShields.begin(); i != vDamageShields.end(); i = next) - { - ++next; - if (alreadyDone.find(*i) == alreadyDone.end()) - { - alreadyDone.insert(*i); - pVictim->SpellNonMeleeDamageLog(this, (*i)->GetId(), (*i)->GetModifierValue(), false, false); - if (pVictim->m_removedAuras > removedAuras) - { - removedAuras = pVictim->m_removedAuras; - next = vDamageShields.begin(); - } - } - } -}*/ - void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool extra ) { if(hasUnitState(UNIT_STAT_CANNOT_AUTOATTACK) || HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) ) @@ -2731,67 +2230,6 @@ void Unit::AttackerStateUpdate (Unit *pVictim, WeaponAttackType attType, bool ex } } -/* -MeleeHitOutcome Unit::RollPhysicalOutcomeAgainst (Unit const *pVictim, WeaponAttackType attType, SpellEntry const *spellInfo) -{ - // Miss chance based on melee - float miss_chance = MeleeMissChanceCalc(pVictim, attType); - - // Critical hit chance - float crit_chance = GetUnitCriticalChance(attType, pVictim); - // this is to avoid compiler issue when declaring variables inside if - float block_chance, parry_chance, dodge_chance; - - // cannot be dodged/parried/blocked - if(spellInfo->Attributes & SPELL_ATTR_IMPOSSIBLE_DODGE_PARRY_BLOCK) - { - block_chance = 0.0f; - parry_chance = 0.0f; - dodge_chance = 0.0f; - } - else - { - // parry can be avoided only by some abilities - parry_chance = pVictim->GetUnitParryChance(); - // block might be bypassed by it as well - block_chance = pVictim->GetUnitBlockChance(); - // stunned target cannot dodge and this is check in GetUnitDodgeChance() - dodge_chance = pVictim->GetUnitDodgeChance(); - } - - // Only players can have Talent&Spell bonuses - if (GetTypeId() == TYPEID_PLAYER) - { - // Increase from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL aura - crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, spellInfo->SchoolMask); - - if( dodge_chance != 0.0f ) // if dodge chance is already 0, ignore talents for speed - { - AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); - for(AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i) - { - // can't be dodged rogue finishing move - if((*i)->GetModifier()->m_miscvalue == VICTIMSTATE_DODGE) - { - if(spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE)) - { - dodge_chance = 0.0f; - break; - } - } - } - } - } - - // Spellmods - if(Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CRITICAL_CHANCE, crit_chance); - - DEBUG_LOG("PHYSICAL OUTCOME: miss %f crit %f dodge %f parry %f block %f",miss_chance,crit_chance,dodge_chance,parry_chance, block_chance); - - return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100),int32(dodge_chance*100),int32(parry_chance*100),int32(block_chance*100), true); -}*/ - MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit *pVictim, WeaponAttackType attType) const { // This is only wrapper @@ -2811,10 +2249,10 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit *pVictim, WeaponAttackT // Useful if want to specify crit & miss chances for melee, else it could be removed DEBUG_LOG("MELEE OUTCOME: miss %f crit %f dodge %f parry %f block %f", miss_chance,crit_chance,dodge_chance,parry_chance,block_chance); - return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100), int32(dodge_chance*100),int32(parry_chance*100),int32(block_chance*100), false); + return RollMeleeOutcomeAgainst(pVictim, attType, int32(crit_chance*100), int32(miss_chance*100), int32(dodge_chance*100),int32(parry_chance*100),int32(block_chance*100)); } -MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance, bool SpellCasted ) const +MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const { if(pVictim->GetTypeId()==TYPEID_UNIT && ((Creature*)pVictim)->IsInEvadeMode()) return MELEE_HIT_EVADE; @@ -2827,7 +2265,6 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack // bonus from skills is 0.04% int32 skillBonus = 4 * ( attackerWeaponSkill - victimMaxSkillValueForLevel ); - int32 skillBonus2 = 4 * ( attackerMaxSkillValueForLevel - victimDefenseSkill ); int32 sum = 0, tmp = 0; int32 roll = urand (0, 10000); @@ -2865,6 +2302,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack // Modify dodge chance by attacker SPELL_AURA_MOD_COMBAT_RESULT_CHANCE dodge_chance+= GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE); + dodge_chance = int32 (float (dodge_chance) * GetTotalAuraMultiplier(SPELL_AURA_MOD_ENEMY_DODGE)); tmp = dodge_chance; if ( (tmp > 0) // check if unit _can_ dodge @@ -2908,16 +2346,6 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack && ((tmp -= skillBonus) > 0) && (roll < (sum += tmp))) { - // Critical chance - tmp = crit_chance + skillBonus2; - if ( GetTypeId() == TYPEID_PLAYER && SpellCasted && tmp > 0 ) - { - if ( roll_chance_i(tmp/100)) - { - DEBUG_LOG ("RollMeleeOutcomeAgainst: BLOCKED CRIT"); - return MELEE_HIT_BLOCK_CRIT; - } - } DEBUG_LOG ("RollMeleeOutcomeAgainst: BLOCK <%d, %d)", sum-tmp, sum); return MELEE_HIT_BLOCK; } @@ -2925,7 +2353,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack } // Critical chance - tmp = crit_chance + skillBonus2; + tmp = crit_chance; if (tmp > 0 && roll < (sum += tmp)) { @@ -2934,7 +2362,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack } // Max 40% chance to score a glancing blow against mobs that are higher level (can do only players and pets and not with ranged weapon) - if( attType != RANGED_ATTACK && !SpellCasted && + if( attType != RANGED_ATTACK && (GetTypeId() == TYPEID_PLAYER || ((Creature*)this)->isPet()) && pVictim->GetTypeId() != TYPEID_PLAYER && !((Creature*)pVictim)->isPet() && getLevel() < pVictim->getLevelForTarget(this) ) @@ -2953,10 +2381,14 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack } } - if(GetTypeId()!=TYPEID_PLAYER && !(((Creature*)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRUSH) && !((Creature*)this)->isPet() && !SpellCasted /*Only autoattack can be crushing blow*/ ) + // mobs can score crushing blows if they're 4 or more levels above victim + if (getLevelForTarget(pVictim) >= pVictim->getLevelForTarget(this) + 4 && + // can be from by creature (if can) or from controlled player that considered as creature + (GetTypeId()!=TYPEID_PLAYER && !((Creature*)this)->isPet() && + !(((Creature*)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_CRUSH) || + GetTypeId()==TYPEID_PLAYER && GetCharmerOrOwnerGUID())) { - // mobs can score crushing blows if they're 3 or more levels above victim - // or when their weapon skill is 15 or more above victim's defense skill + // when their weapon skill is 15 or more above victim's defense skill tmp = victimDefenseSkill; int32 tmpmax = victimMaxSkillValueForLevel; // having defense above your maximum (from items, talents etc.) has no effect @@ -3066,6 +2498,23 @@ bool Unit::isSpellBlocked(Unit *pVictim, SpellEntry const *spellProto, WeaponAtt { if (pVictim->HasInArc(M_PI,this)) { + /* Currently not exist spells with ignore block + // Ignore combat result aura (parry/dodge check on prepare) + AuraList const& ignore = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); + for(AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) + { + if (!(*i)->isAffectedOnSpell(spellProto)) + continue; + if ((*i)->GetModifier()->m_miscvalue == ) + return false; + } + */ + + // Check creatures flags_extra for disable block + if(pVictim->GetTypeId()==TYPEID_UNIT && + ((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_BLOCK ) + return false; + float blockChance = GetUnitBlockChance(); blockChance += (GetWeaponSkillValue(attackType) - pVictim->GetMaxSkillValueForLevel() )*0.04; if (roll_chance_f(blockChance)) @@ -3074,24 +2523,27 @@ bool Unit::isSpellBlocked(Unit *pVictim, SpellEntry const *spellProto, WeaponAtt return false; } +bool Unit::isBlockCritical() +{ + if (roll_chance_i(GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_CRIT_CHANCE))) + return true; + return false; +} + // Melee based spells can be miss, parry or dodge on this step // Crit or block - determined on damage calculation phase! (and can be both in some time) -float Unit::MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const +/*float Unit::MeleeSpellMissChance(Unit *pVictim, WeaponAttackType attType, int32 skillDiff, SpellEntry const *spell) { // Calculate hit chance (more correct for chance mod) int32 HitChance; // PvP - PvE melee chances - /*int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 5 : 7; + int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 5 : 7; int32 leveldif = pVictim->getLevelForTarget(this) - getLevelForTarget(pVictim); if(leveldif < 3) HitChance = 95 - leveldif; else - HitChance = 93 - (leveldif - 2) * lchance;*/ - if (spellId || attType == RANGED_ATTACK || !haveOffhandWeapon()) - HitChance = 95.0f; - else - HitChance = 76.0f; + HitChance = 93 - (leveldif - 2) * lchance; // Hit chance depends from victim auras if(attType == RANGED_ATTACK) @@ -3100,11 +2552,8 @@ float Unit::MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType, HitChance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE); // Spellmod from SPELLMOD_RESIST_MISS_CHANCE - if(spellId) - { - if(Player *modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_MISS_CHANCE, HitChance); - } + if(Player *modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spell->Id, SPELLMOD_RESIST_MISS_CHANCE, HitChance); // Miss = 100 - hit float miss_chance= 100.0f - HitChance; @@ -3116,12 +2565,7 @@ float Unit::MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType, miss_chance -= m_modMeleeHitChance; // bonus from skills is 0.04% - //miss_chance -= skillDiff * 0.04f; - int32 diff = -skillDiff; - if(pVictim->GetTypeId()==TYPEID_PLAYER) - miss_chance += diff > 0 ? diff * 0.04 : diff * 0.02; - else - miss_chance += diff > 10 ? 2 + (diff - 10) * 0.4 : diff * 0.1; + miss_chance -= skillDiff * 0.04f; // Limit miss chance from 0 to 60% if (miss_chance < 0.0f) @@ -3129,7 +2573,7 @@ float Unit::MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType, if (miss_chance > 60.0f) return 60.0f; return miss_chance; -} +}*/ // Melee based spells hit result calculations SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell) @@ -3145,68 +2589,107 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell) int32 fullSkillDiff = attackerWeaponSkill - int32(pVictim->GetDefenseSkillValue(this)); uint32 roll = urand (0, 10000); - uint32 missChance = uint32(MeleeSpellMissChance(pVictim, attType, fullSkillDiff, spell->Id)*100.0f); + uint32 missChance = uint32(MeleeSpellMissChance(pVictim, attType, fullSkillDiff, spell->Id)*100.0f); // Roll miss uint32 tmp = missChance; if (roll < tmp) return SPELL_MISS_MISS; + // Chance resist mechanic (select max value from every mechanic spell effect) + int32 resist_mech = 0; + // Get effects mechanic and chance + for(int eff = 0; eff < 3; ++eff) + { + int32 effect_mech = GetEffectMechanic(spell, eff); + if (effect_mech) + { + int32 temp = pVictim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effect_mech); + if (resist_mech < temp*100) + resist_mech = temp*100; + } + } + // Roll chance + tmp += resist_mech; + if (roll < tmp) + return SPELL_MISS_RESIST; + + bool canDodge = true; + bool canParry = true; + // Same spells cannot be parry/dodge if (spell->Attributes & SPELL_ATTR_IMPOSSIBLE_DODGE_PARRY_BLOCK) return SPELL_MISS_NONE; - // Ranged attack can`t miss too + // Ranged attack cannot be parry/dodge if (attType == RANGED_ATTACK) return SPELL_MISS_NONE; - bool attackFromBehind = !pVictim->HasInArc(M_PI,this); - - // Roll dodge - int32 dodgeChance = int32(pVictim->GetUnitDodgeChance()*100.0f) - skillDiff * 4; - // Reduce enemy dodge chance by SPELL_AURA_MOD_COMBAT_RESULT_CHANCE - dodgeChance+= GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE); - - // Reduce dodge chance by attacker expertise rating - if (GetTypeId() == TYPEID_PLAYER) - dodgeChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f); - if (dodgeChance < 0) - dodgeChance = 0; - - // Can`t dodge from behind in PvP (but its possible in PvE) - if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER && attackFromBehind) - dodgeChance = 0; - - // Rogue talent`s cant be dodged - AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); - for(AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i) + // Check for attack from behind + if (!pVictim->HasInArc(M_PI,this)) { - if((*i)->GetModifier()->m_miscvalue == VICTIMSTATE_DODGE) // can't be dodged rogue finishing move + // Can`t dodge from behind in PvP (but its possible in PvE) + if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER) + canDodge = false; + // Can`t parry + canParry = false; + } + // Check creatures flags_extra for disable parry + if(pVictim->GetTypeId()==TYPEID_UNIT) + { + uint32 flagEx = ((Creature*)pVictim)->GetCreatureInfo()->flags_extra; + if( flagEx & CREATURE_FLAG_EXTRA_NO_PARRY ) + canParry = false; + } + // Ignore combat result aura + AuraList const& ignore = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); + for(AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) + { + if (!(*i)->isAffectedOnSpell(spell)) + continue; + switch((*i)->GetModifier()->m_miscvalue) { - if(spell->SpellFamilyName==SPELLFAMILY_ROGUE && (spell->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE)) - { - dodgeChance = 0; + case MELEE_HIT_DODGE: canDodge = false; break; + case MELEE_HIT_BLOCK: break; // Block check in hit step + case MELEE_HIT_PARRY: canParry = false; break; + default: + DEBUG_LOG("Spell %u SPELL_AURA_IGNORE_COMBAT_RESULT have unhandled state %d", (*i)->GetId(), (*i)->GetModifier()->m_miscvalue); break; - } } } - tmp += dodgeChance; - if (roll < tmp) - return SPELL_MISS_DODGE; + if (canDodge) + { + // Roll dodge + int32 dodgeChance = int32(pVictim->GetUnitDodgeChance()*100.0f) - skillDiff * 4; + // Reduce enemy dodge chance by SPELL_AURA_MOD_COMBAT_RESULT_CHANCE + dodgeChance+= GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE); + dodgeChance = int32 (float (dodgeChance) * GetTotalAuraMultiplier(SPELL_AURA_MOD_ENEMY_DODGE)); + // Reduce dodge chance by attacker expertise rating + if (GetTypeId() == TYPEID_PLAYER) + dodgeChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f); + if (dodgeChance < 0) + dodgeChance = 0; - // Roll parry - int32 parryChance = int32(pVictim->GetUnitParryChance()*100.0f) - skillDiff * 4; - // Reduce parry chance by attacker expertise rating - if (GetTypeId() == TYPEID_PLAYER) - parryChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f); - // Can`t parry from behind - if (parryChance < 0 || attackFromBehind) - parryChance = 0; + tmp += dodgeChance; + if (roll < tmp) + return SPELL_MISS_DODGE; + } - tmp += parryChance; - if (roll < tmp) - return SPELL_MISS_PARRY; + if (canParry) + { + // Roll parry + int32 parryChance = int32(pVictim->GetUnitParryChance()*100.0f) - skillDiff * 4; + // Reduce parry chance by attacker expertise rating + if (GetTypeId() == TYPEID_PLAYER) + parryChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f); + if (parryChance < 0) + parryChance = 0; + + tmp += parryChance; + if (roll < tmp) + return SPELL_MISS_PARRY; + } return SPELL_MISS_NONE; } @@ -3297,8 +2780,8 @@ SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool if (spell->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) return SPELL_MISS_NONE; - // Check for immune (use charges) - if (pVictim->IsImmunedToSpell(spell,true)) + // Check for immune + if (pVictim->IsImmunedToSpell(spell)) return SPELL_MISS_IMMUNE; // All positive spells can`t miss @@ -3307,8 +2790,8 @@ SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool &&(!IsHostileTo(pVictim))) //prevent from affecting enemy by "positive" spell return SPELL_MISS_NONE; - // Check for immune (use charges) - if (pVictim->IsImmunedToDamage(GetSpellSchoolMask(spell),true)) + // Check for immune + if (pVictim->IsImmunedToDamage(GetSpellSchoolMask(spell))) return SPELL_MISS_IMMUNE; if(this == pVictim) @@ -3321,7 +2804,7 @@ SpellMissInfo Unit::SpellHitResult(Unit *pVictim, SpellEntry const *spell, bool Unit::AuraList const& mReflectSpellsSchool = pVictim->GetAurasByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL); for(Unit::AuraList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i) if((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spell)) - reflectchance = (*i)->GetModifierValue(); + reflectchance += (*i)->GetModifier()->m_amount; if (reflectchance > 0 && roll_chance_i(reflectchance)) { // Start triggers for remove charges if need (trigger only for victim, and mark as active spell) @@ -3496,7 +2979,7 @@ float Unit::GetUnitBlockChance() const Player const* player = (Player const*)this; if(player->CanBlock() ) { - Item *tmpitem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + Item *tmpitem = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); if(tmpitem && !tmpitem->IsBroken() && tmpitem->GetProto()->Block) return GetFloatValue(PLAYER_BLOCK_PERCENTAGE); } @@ -3562,6 +3045,9 @@ float Unit::GetUnitCriticalChance(WeaponAttackType attackType, const Unit *pVict crit -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_MELEE); } + // Apply crit chance from defence skill + crit += (int32(GetMaxSkillValueForLevel(pVictim)) - int32(pVictim->GetDefenseSkillValue(this))) * 0.04f; + if (crit < 0.0f) crit = 0.0f; return crit; @@ -3693,7 +3179,7 @@ void Unit::_UpdateAutoRepeatSpell() if ( (GetTypeId() == TYPEID_PLAYER && ((Player*)this)->isMoving()) || IsNonMeleeSpellCasted(false,false,true) ) { // cancel wand shoot - if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351) + if(m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != SPELL_ID_AUTOSHOT) InterruptSpell(CURRENT_AUTOREPEAT_SPELL); m_AutoRepeatFirstCast = true; return; @@ -3746,7 +3232,7 @@ void Unit::SetCurrentCastedSpell( Spell * pSpell ) if ( m_currentSpells[CURRENT_AUTOREPEAT_SPELL] ) { // break autorepeat if not Auto Shot - if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351) + if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != SPELL_ID_AUTOSHOT) InterruptSpell(CURRENT_AUTOREPEAT_SPELL); m_AutoRepeatFirstCast = true; } @@ -3761,7 +3247,7 @@ void Unit::SetCurrentCastedSpell( Spell * pSpell ) // it also does break autorepeat if not Auto Shot if ( m_currentSpells[CURRENT_AUTOREPEAT_SPELL] && - m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Category == 351 ) + m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id != SPELL_ID_AUTOSHOT ) InterruptSpell(CURRENT_AUTOREPEAT_SPELL); addUnitState(UNIT_STAT_CASTING); } break; @@ -3769,7 +3255,7 @@ void Unit::SetCurrentCastedSpell( Spell * pSpell ) case CURRENT_AUTOREPEAT_SPELL: { // only Auto Shoot does not break anything - if (pSpell->m_spellInfo->Category == 351) + if (pSpell->m_spellInfo->Id != SPELL_ID_AUTOSHOT) { // generic autorepeats break generic non-delayed and channeled non-delayed spells InterruptSpell(CURRENT_GENERIC_SPELL,false); @@ -3932,13 +3418,23 @@ void Unit::DeMorph() SetDisplayId(GetNativeDisplayId()); } +bool Unit::HasAuraTypeWithMiscvalue(AuraType auratype, uint32 miscvalue) const +{ + AuraList const& mTotalAuraList = GetAurasByType(auratype); + for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) + if (miscvalue == (*i)->GetModifier()->m_miscvalue) + return true; + + return false; +} + int32 Unit::GetTotalAuraModifier(AuraType auratype) const { int32 modifier = 0; AuraList const& mTotalAuraList = GetAurasByType(auratype); for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) - modifier += (*i)->GetModifierValue(); + modifier += (*i)->GetModifier()->m_amount; return modifier; } @@ -3949,7 +3445,7 @@ float Unit::GetTotalAuraMultiplier(AuraType auratype) const AuraList const& mTotalAuraList = GetAurasByType(auratype); for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) - multiplier *= (100.0f + (*i)->GetModifierValue())/100.0f; + multiplier *= (100.0f + (*i)->GetModifier()->m_amount)/100.0f; return multiplier; } @@ -3960,11 +3456,8 @@ int32 Unit::GetMaxPositiveAuraModifier(AuraType auratype) const AuraList const& mTotalAuraList = GetAurasByType(auratype); for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) - { - int32 amount = (*i)->GetModifierValue(); - if (amount > modifier) - modifier = amount; - } + if ((*i)->GetModifier()->m_amount > modifier) + modifier = (*i)->GetModifier()->m_amount; return modifier; } @@ -3975,11 +3468,8 @@ int32 Unit::GetMaxNegativeAuraModifier(AuraType auratype) const AuraList const& mTotalAuraList = GetAurasByType(auratype); for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) - { - int32 amount = (*i)->GetModifierValue(); - if (amount < modifier) - modifier = amount; - } + if ((*i)->GetModifier()->m_amount < modifier) + modifier = (*i)->GetModifier()->m_amount; return modifier; } @@ -3993,7 +3483,7 @@ int32 Unit::GetTotalAuraModifierByMiscMask(AuraType auratype, uint32 misc_mask) { Modifier* mod = (*i)->GetModifier(); if (mod->m_miscvalue & misc_mask) - modifier += (*i)->GetModifierValue(); + modifier += mod->m_amount; } return modifier; } @@ -4007,7 +3497,7 @@ float Unit::GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask { Modifier* mod = (*i)->GetModifier(); if (mod->m_miscvalue & misc_mask) - multiplier *= (100.0f + (*i)->GetModifierValue())/100.0f; + multiplier *= (100.0f + mod->m_amount)/100.0f; } return multiplier; } @@ -4020,9 +3510,8 @@ int32 Unit::GetMaxPositiveAuraModifierByMiscMask(AuraType auratype, uint32 misc_ for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) { Modifier* mod = (*i)->GetModifier(); - int32 amount = (*i)->GetModifierValue(); - if (mod->m_miscvalue & misc_mask && amount > modifier) - modifier = amount; + if (mod->m_miscvalue & misc_mask && mod->m_amount > modifier) + modifier = mod->m_amount; } return modifier; @@ -4036,9 +3525,8 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscMask(AuraType auratype, uint32 misc_ for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) { Modifier* mod = (*i)->GetModifier(); - int32 amount = (*i)->GetModifierValue(); - if (mod->m_miscvalue & misc_mask && amount < modifier) - modifier = amount; + if (mod->m_miscvalue & misc_mask && mod->m_amount < modifier) + modifier = mod->m_amount; } return modifier; @@ -4053,7 +3541,7 @@ int32 Unit::GetTotalAuraModifierByMiscValue(AuraType auratype, int32 misc_value) { Modifier* mod = (*i)->GetModifier(); if (mod->m_miscvalue == misc_value) - modifier += (*i)->GetModifierValue(); + modifier += mod->m_amount; } return modifier; } @@ -4067,7 +3555,7 @@ float Unit::GetTotalAuraMultiplierByMiscValue(AuraType auratype, int32 misc_valu { Modifier* mod = (*i)->GetModifier(); if (mod->m_miscvalue == misc_value) - multiplier *= (100.0f + (*i)->GetModifierValue())/100.0f; + multiplier *= (100.0f + mod->m_amount)/100.0f; } return multiplier; } @@ -4080,9 +3568,8 @@ int32 Unit::GetMaxPositiveAuraModifierByMiscValue(AuraType auratype, int32 misc_ for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) { Modifier* mod = (*i)->GetModifier(); - int32 amount = (*i)->GetModifierValue(); - if (mod->m_miscvalue == misc_value && amount > modifier) - modifier = amount; + if (mod->m_miscvalue == misc_value && mod->m_amount > modifier) + modifier = mod->m_amount; } return modifier; @@ -4096,9 +3583,8 @@ int32 Unit::GetMaxNegativeAuraModifierByMiscValue(AuraType auratype, int32 misc_ for(AuraList::const_iterator i = mTotalAuraList.begin();i != mTotalAuraList.end(); ++i) { Modifier* mod = (*i)->GetModifier(); - int32 amount = (*i)->GetModifierValue(); - if (mod->m_miscvalue == misc_value && amount < modifier) - modifier = amount; + if (mod->m_miscvalue == misc_value && mod->m_amount < modifier) + modifier = mod->m_amount; } return modifier; @@ -4134,57 +3620,51 @@ bool Unit::AddAura(Aura *Aur) // passive and persistent auras can stack with themselves any number of times if (!Aur->IsPassive() && !Aur->IsPersistent()) { - // replace aura if next will > spell StackAmount - if(aurSpellInfo->StackAmount) + for(AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair); ++i2) { - Aur->SetStackAmount(i->second->GetStackAmount()); - if(Aur->GetStackAmount() < aurSpellInfo->StackAmount) - Aur->SetStackAmount(Aur->GetStackAmount()+1); - RemoveAura(i,AURA_REMOVE_BY_STACK); - } - // if StackAmount==0 not allow auras from same caster - else - { - for(AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair); ++i2) + if(i2->second->GetCasterGUID()==Aur->GetCasterGUID()) { - if(i2->second->GetCasterGUID()==Aur->GetCasterGUID()) - { - // can be only single (this check done at _each_ aura add - RemoveAura(i2,AURA_REMOVE_BY_STACK); - break; - } - - bool stop = false; - switch(aurSpellInfo->EffectApplyAuraName[Aur->GetEffIndex()]) + // Aura can stack on self -> Stack it; + if(aurSpellInfo->StackAmount) { - // DoT/HoT/etc - case SPELL_AURA_PERIODIC_DAMAGE: // allow stack - case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: - case SPELL_AURA_PERIODIC_LEECH: - case SPELL_AURA_PERIODIC_HEAL: - case SPELL_AURA_OBS_MOD_HEALTH: - case SPELL_AURA_PERIODIC_MANA_LEECH: - case SPELL_AURA_PERIODIC_ENERGIZE: - case SPELL_AURA_OBS_MOD_MANA: - case SPELL_AURA_POWER_BURN_MANA: - break; - default: // not allow - // can be only single (this check done at _each_ aura add - RemoveAura(i2,AURA_REMOVE_BY_STACK); - stop = true; - break; + i2->second->modStackAmount(1); + delete Aur; + return false; } + // can be only single (this check done at _each_ aura add + RemoveAura(i2,AURA_REMOVE_BY_STACK); + break; + } - if(stop) + bool stop = false; + switch(aurSpellInfo->EffectApplyAuraName[Aur->GetEffIndex()]) + { + // DoT/HoT/etc + case SPELL_AURA_PERIODIC_DAMAGE: // allow stack + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_OBS_MOD_HEALTH: + case SPELL_AURA_PERIODIC_MANA_LEECH: + case SPELL_AURA_PERIODIC_ENERGIZE: + case SPELL_AURA_OBS_MOD_MANA: + case SPELL_AURA_POWER_BURN_MANA: + break; + default: // not allow + // can be only single (this check done at _each_ aura add + RemoveAura(i2,AURA_REMOVE_BY_STACK); + stop = true; break; } + + if(stop) + break; } } } - // passive auras stack with all (except passive spell proc auras) - if ((!Aur->IsPassive() || !IsPassiveStackableSpell(Aur->GetId())) && - !(Aur->GetId() == 20584 || Aur->GetId() == 8326)) + // passive auras not stacable with other ranks + if (!IsPassiveSpellStackableWithRanks(aurSpellInfo)) { if (!RemoveNoStackAurasDueToAura(Aur)) { @@ -4302,6 +3782,13 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur) uint32 spellId = Aur->GetId(); uint32 effIndex = Aur->GetEffIndex(); + // passive spell special case (only non stackable with ranks) + if(IsPassiveSpell(spellId)) + { + if(IsPassiveSpellStackableWithRanks(spellProto)) + return true; + } + SpellSpecific spellId_spec = GetSpellSpecific(spellId); AuraMap::iterator i,next; @@ -4318,9 +3805,11 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur) uint32 i_spellId = i_spellProto->Id; + // early checks that spellId is passive non stackable spell if(IsPassiveSpell(i_spellId)) { - if(IsPassiveStackableSpell(i_spellId)) + // passive non-stackable spells not stackable only for same caster + if(Aur->GetCasterGUID()!=i->second->GetCasterGUID()) continue; // passive non-stackable spells not stackable only with another rank of same spell @@ -4337,65 +3826,36 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur) for(int j = 0; j < 3; ++j) if (i_spellProto->EffectTriggerSpell[j] == spellProto->Id) is_triggered_by_spell = true; - if (is_triggered_by_spell) continue; - for(int j = 0; j < 3; ++j) - { - // prevent remove dummy triggered spells at next effect aura add - switch(spellProto->Effect[j]) // main spell auras added added after triggered spell - { - case SPELL_EFFECT_DUMMY: - switch(spellId) - { - case 5420: if(i_spellId==34123) is_triggered_by_spell = true; break; - } - break; - } + if (is_triggered_by_spell) + continue; - if(is_triggered_by_spell) - break; + // check if they can stack + bool sameCaster = Aur->GetCasterGUID() == (*i).second->GetCasterGUID(); + if(!spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId, sameCaster)) + continue; - // prevent remove form main spell by triggered passive spells - switch(i_spellProto->EffectApplyAuraName[j]) // main aura added before triggered spell - { - case SPELL_AURA_MOD_SHAPESHIFT: - switch(i_spellId) - { - case 24858: if(spellId==24905) is_triggered_by_spell = true; break; - case 33891: if(spellId==5420 || spellId==34123) is_triggered_by_spell = true; break; - case 34551: if(spellId==22688) is_triggered_by_spell = true; break; - } - break; - } - } + //some spells should be not removed by lower rank of them (totem, paladin aura) + if (!sameCaster + &&(spellProto->Effect[effIndex]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY) + &&(spellProto->DurationIndex==21) + &&(spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId)) + &&(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)) + return false; - if(!is_triggered_by_spell) + // Its a parent aura (create this aura in ApplyModifier) + if ((*i).second->IsInUse()) { - bool sameCaster = Aur->GetCasterGUID() == (*i).second->GetCasterGUID(); - if( spellmgr.IsNoStackSpellDueToSpell(spellId, i_spellId, sameCaster) ) - { - //some spells should be not removed by lower rank of them (totem, paladin aura) - if (!sameCaster - &&(spellProto->Effect[effIndex]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY) - &&(spellProto->DurationIndex==21) - &&(spellmgr.IsRankSpellDueToSpell(spellProto, i_spellId)) - &&(CompareAuraRanks(spellId, effIndex, i_spellId, i_effIndex) < 0)) - return false; + sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex()); + continue; + } - // Its a parent aura (create this aura in ApplyModifier) - if ((*i).second->IsInUse()) - { - sLog.outError("Aura (Spell %u Effect %u) is in process but attempt removed at aura (Spell %u Effect %u) adding, need add stack rule for Unit::RemoveNoStackAurasDueToAura", i->second->GetId(), i->second->GetEffIndex(),Aur->GetId(), Aur->GetEffIndex()); - continue; - } - RemoveAurasDueToSpell(i_spellId); + RemoveAurasDueToSpell(i_spellId); - if( m_Auras.empty() ) - break; - else - next = m_Auras.begin(); - } - } + if( m_Auras.empty() ) + break; + else + next = m_Auras.begin(); } return true; } @@ -4415,6 +3875,18 @@ void Unit::RemoveAura(uint32 spellId, uint32 effindex, Aura* except) } } +void Unit::RemoveAurasByCasterSpell(uint32 spellId, uint64 casterGUID) +{ + for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ) + { + Aura *aur = iter->second; + if (aur->GetId() == spellId && aur->GetCasterGUID() == casterGUID) + RemoveAura(iter); + else + ++iter; + } +} + void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler) { for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ) @@ -4424,20 +3896,21 @@ void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit { // Custom dispel case // Unstable Affliction - if (aur->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (aur->GetSpellProto()->SpellFamilyFlags & 0x010000000000LL)) + if (aur->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && (aur->GetSpellProto()->SpellFamilyFlags[1] & 0x0100)) { int32 damage = aur->GetModifier()->m_amount*9; uint64 caster_guid = aur->GetCasterGUID(); // Remove aura - RemoveAura(iter, AURA_REMOVE_BY_DISPEL); + if (iter->second->modStackAmount(-1)) + RemoveAura(iter, AURA_REMOVE_BY_DISPEL); // backfire damage and silence dispeler->CastCustomSpell(dispeler, 31117, &damage, NULL, NULL, true, NULL, NULL,caster_guid); iter = m_Auras.begin(); // iterator can be invalidate at cast if self-dispel } - else + else if (iter->second->modStackAmount(-1)) RemoveAura(iter, AURA_REMOVE_BY_DISPEL); } else @@ -4469,7 +3942,8 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit stealer->AddAura(new_aur); // Remove aura as dispel - RemoveAura(iter, AURA_REMOVE_BY_DISPEL); + if (iter->second->modStackAmount(-1)) + RemoveAura(iter, AURA_REMOVE_BY_DISPEL); } else ++iter; @@ -4507,73 +3981,26 @@ void Unit::RemoveAurasWithDispelType( DispelType type ) } } -void Unit::RemoveSingleAuraFromStackByDispel(uint32 spellId) -{ - for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ) - { - Aura *aur = iter->second; - if (aur->GetId() == spellId) - { - if(iter->second->GetStackAmount() > 1) - { - // reapply modifier with reduced stack amount - iter->second->ApplyModifier(false,true); - iter->second->SetStackAmount(iter->second->GetStackAmount()-1); - iter->second->ApplyModifier(true,true); - - iter->second->UpdateSlotCounterAndDuration(); - return; // not remove aura if stack amount > 1 - } - else - RemoveAura(iter,AURA_REMOVE_BY_DISPEL); - } - else - ++iter; - } -} - void Unit::RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex) { AuraMap::iterator iter = m_Auras.find(spellEffectPair(spellId, effindex)); if(iter != m_Auras.end()) { - if(iter->second->GetStackAmount() > 1) - { - // reapply modifier with reduced stack amount - iter->second->ApplyModifier(false,true); - iter->second->SetStackAmount(iter->second->GetStackAmount()-1); - iter->second->ApplyModifier(true,true); - - iter->second->UpdateSlotCounterAndDuration(); - return; // not remove aura if stack amount > 1 - } - RemoveAura(iter); + if (iter->second->modStackAmount(-1)) + RemoveAura(iter); } } -void Unit::RemoveAurasDueToSpell(uint32 spellId, Aura* except) +void Unit::RemoveSingleSpellAurasFromStack(uint32 spellId) { - for (int i = 0; i < 3; ++i) - RemoveAura(spellId,i,except); + for (int i=0; i<3; ++i) + RemoveSingleAuraFromStack(spellId, i); } -void Unit::RemoveAurasDueToCasterSpell(uint32 spellId, uint64 guid) +void Unit::RemoveAurasDueToSpell(uint32 spellId, Aura* except) { - for (int k=0; k < 3; ++k) - { - spellEffectPair spair = spellEffectPair(spellId, k); - for (AuraMap::iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair);) - { - if (iter->second->GetCasterGUID() == guid) - { - RemoveAura(iter); - break; - //iter = m_Auras.upper_bound(spair); // overwrite by more appropriate - } - else - ++iter; - } - } + for (int i = 0; i < 3; ++i) + RemoveAura(spellId,i,except); } void Unit::RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId) @@ -4703,9 +4130,6 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) sLog.outDebug("Aura %u (%u) now is remove mode %d", Aur->GetId(), Aur->GetModifier()->m_auraname, mode); assert(!Aur->IsInUse()); Aur->ApplyModifier(false,true); - - Aur->SetStackAmount(0); - Aur->_RemoveAura(); if(mode != AURA_REMOVE_BY_STACK) @@ -4798,7 +4222,8 @@ void Unit::DelayAura(uint32 spellId, uint32 effindex, int32 delaytime) iter->second->SetAuraDuration(0); else iter->second->SetAuraDuration(iter->second->GetAuraDuration() - delaytime); - iter->second->UpdateAuraDuration(); + // update for out of range group members (on 1 slot use) + UpdateAuraForGroup(iter->second->GetAuraSlot()); sLog.outDebug("Aura %u partially interrupted on unit %u, new duration: %u ms",iter->second->GetModifier()->m_auraname, GetGUIDLow(), iter->second->GetAuraDuration()); } } @@ -4827,6 +4252,33 @@ Aura* Unit::GetAura(uint32 spellId, uint32 effindex) return NULL; } +Aura* Unit::GetAura(AuraType type, uint32 family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID) +{ + AuraList const& auras = GetAurasByType(type); + for(AuraList::const_iterator i = auras.begin();i != auras.end(); ++i) + { + SpellEntry const *spell = (*i)->GetSpellProto(); + if (spell->SpellFamilyName == family && spell->SpellFamilyFlags.HasFlag(familyFlag1, familyFlag2, familyFlag3)) + { + if (casterGUID && (*i)->GetCasterGUID()!=casterGUID) + continue; + return (*i); + } + } + return NULL; +} + +bool Unit::HasAura(uint32 spellId) const +{ + for (int i = 0; i < 3 ; ++i) + { + AuraMap::const_iterator iter = m_Auras.find(spellEffectPair(spellId, i)); + if (iter != m_Auras.end()) + return true; + } + return false; +} + void Unit::AddDynObject(DynamicObject* dynObj) { m_dynObjGUIDs.push_back(dynObj->GetGUID()); @@ -4971,6 +4423,7 @@ void Unit::SendSpellNonMeleeDamageLog(SpellNonMeleeDamage *log) data.append(log->attacker->GetPackGUID()); data << uint32(log->SpellID); data << uint32(log->damage); //damage amount + data << uint32(0); data << uint8 (log->schoolMask); //damage school data << uint32(log->absorb); //AbsorbedDamage data << uint32(log->resist); //resist @@ -4990,6 +4443,7 @@ void Unit::SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, data.append(GetPackGUID()); data << uint32(SpellID); data << uint32(Damage-AbsorbedDamage-Resist-Blocked); + data << uint32(0); // wotlk data << uint8(damageSchoolMask); // spell school data << uint32(AbsorbedDamage); // AbsorbedDamage data << uint32(Resist); // resist @@ -5028,25 +4482,65 @@ void Unit::SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo) void Unit::SendAttackStateUpdate(CalcDamageInfo *damageInfo) { - WorldPacket data(SMSG_ATTACKERSTATEUPDATE, (16+84)); // we guess size + uint32 count = 1; + WorldPacket data(SMSG_ATTACKERSTATEUPDATE, (16+45)); // we guess size data << (uint32)damageInfo->HitInfo; data.append(GetPackGUID()); data.append(damageInfo->target->GetPackGUID()); data << (uint32)(damageInfo->damage); // Full damage + data << uint32(0); // overkill value + + data << (uint8)count; // Sub damage count + + for(int i = 0; i < count; ++i) + { + data << (uint32)(damageInfo->damageSchoolMask); // School of sub damage + data << (float)damageInfo->damage; // sub damage + data << (uint32)damageInfo->damage; // Sub Damage + } + + if(damageInfo->HitInfo & (HITINFO_ABSORB | HITINFO_ABSORB2)) + { + for(int i = 0; i < count; ++i) + data << (uint32)damageInfo->absorb; // Absorb + } + + if(damageInfo->HitInfo & (HITINFO_RESIST | HITINFO_RESIST2)) + { + for(int i = 0; i < count; ++i) + data << (uint32)damageInfo->resist; // Resist + } - data << (uint8)1; // Sub damage count - //=== Sub damage description - data << (uint32)(damageInfo->damageSchoolMask); // School of sub damage - data << (float)damageInfo->damage; // sub damage - data << (uint32)damageInfo->damage; // Sub Damage - data << (uint32)damageInfo->absorb; // Absorb - data << (uint32)damageInfo->resist; // Resist - //================================================= - data << (uint32)damageInfo->TargetState; + data << (uint8)damageInfo->TargetState; data << (uint32)0; data << (uint32)0; - data << (uint32)damageInfo->blocked_amount; - SendMessageToSet( &data, true );/**/ + + if(damageInfo->HitInfo & HITINFO_BLOCK) + data << (uint32)damageInfo->blocked_amount; + + if(damageInfo->HitInfo & HITINFO_UNK3) + data << uint32(0); + + if(damageInfo->HitInfo & HITINFO_UNK1) + { + data << uint32(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + for(uint8 i = 0; i < 5; ++i) + { + data << float(0); + data << float(0); + } + data << uint32(0); + } + + SendMessageToSet( &data, true ); } void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, SpellSchoolMask damageSchoolMask, uint32 Damage, uint32 AbsorbDamage, uint32 Resist, VictimState TargetState, uint32 BlockedAmount) @@ -5054,169 +4548,69 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, sLog.outDebug("WORLD: Sending SMSG_ATTACKERSTATEUPDATE"); WorldPacket data(SMSG_ATTACKERSTATEUPDATE, (16+45)); // we guess size - data << (uint32)HitInfo; + data << uint32(HitInfo); // flags data.append(GetPackGUID()); data.append(target->GetPackGUID()); - data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount); + data << uint32(Damage-AbsorbDamage-Resist-BlockedAmount);// damage + data << uint32(0); // overkill value data << (uint8)SwingType; // count? // for(i = 0; i < SwingType; ++i) data << (uint32)damageSchoolMask; data << (float)(Damage-AbsorbDamage-Resist-BlockedAmount); - // still need to double check damage data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount); - data << (uint32)AbsorbDamage; - data << (uint32)Resist; // end loop - data << (uint32)TargetState; - - if( AbsorbDamage == 0 ) //also 0x3E8 = 0x3E8, check when that happens - data << (uint32)0; - else - data << (uint32)-1; - - data << (uint32)0; - data << (uint32)BlockedAmount; - - SendMessageToSet( &data, true ); -} -/* -void Unit::ProcDamageAndSpell(Unit *pVictim, uint32 procAttacker, uint32 procVictim, uint32 damage, SpellSchoolMask damageSchoolMask, SpellEntry const *procSpell, bool isTriggeredSpell, WeaponAttackType attType) -{ - sLog.outDebug("ProcDamageAndSpell: attacker flags are 0x%x, victim flags 0x%x", procAttacker, procVictim); - if(procSpell) - sLog.outDebug("ProcDamageAndSpell: invoked due to spell id %u %s", procSpell->Id, (isTriggeredSpell?"(triggered)":"")); - - // Assign melee/ranged proc flags for magic attacks, that are actually melee/ranged abilities - // not assign for spell proc triggered spell to prevent infinity (or unexpected 2-3 times) melee damage spell proc call with melee damage effect - // That is the question though if it's fully correct - if(procSpell && !isTriggeredSpell) + if(HitInfo & (HITINFO_ABSORB | HITINFO_ABSORB2)) { - if(procSpell->DmgClass == SPELL_DAMAGE_CLASS_MELEE) - { - if(procAttacker & PROC_FLAG_HIT_SPELL) procAttacker |= PROC_FLAG_HIT_MELEE; - if(procAttacker & PROC_FLAG_CRIT_SPELL) procAttacker |= PROC_FLAG_CRIT_MELEE; - if(procVictim & PROC_FLAG_STRUCK_SPELL) procVictim |= PROC_FLAG_STRUCK_MELEE; - if(procVictim & PROC_FLAG_STRUCK_CRIT_SPELL) procVictim |= PROC_FLAG_STRUCK_CRIT_MELEE; - attType = BASE_ATTACK; // Melee abilities are assumed to be dealt with mainhand weapon - } - else if (procSpell->DmgClass == SPELL_DAMAGE_CLASS_RANGED) - { - if(procAttacker & PROC_FLAG_HIT_SPELL) procAttacker |= PROC_FLAG_HIT_RANGED; - if(procAttacker & PROC_FLAG_CRIT_SPELL) procAttacker |= PROC_FLAG_CRIT_RANGED; - if(procVictim & PROC_FLAG_STRUCK_SPELL) procVictim |= PROC_FLAG_STRUCK_RANGED; - if(procVictim & PROC_FLAG_STRUCK_CRIT_SPELL) procVictim |= PROC_FLAG_STRUCK_CRIT_RANGED; - attType = RANGED_ATTACK; - } + // for(i = 0; i < SwingType; ++i) + data << uint32(AbsorbDamage); + // end loop } - if(damage && (procVictim & (PROC_FLAG_STRUCK_MELEE|PROC_FLAG_STRUCK_RANGED|PROC_FLAG_STRUCK_SPELL))) - procVictim |= (PROC_FLAG_TAKE_DAMAGE|PROC_FLAG_TOUCH); - // Not much to do if no flags are set. - if (procAttacker) + if(HitInfo & (HITINFO_RESIST | HITINFO_RESIST2)) { - // processing auras that not generate casts at proc event before auras that generate casts to prevent proc aura added at prev. proc aura execute in set - ProcDamageAndSpellFor(false,pVictim,procAttacker,attackerProcEffectAuraTypes,attType, procSpell, damage, damageSchoolMask); - ProcDamageAndSpellFor(false,pVictim,procAttacker,attackerProcCastAuraTypes,attType, procSpell, damage, damageSchoolMask); + // for(i = 0; i < SwingType; ++i) + data << uint32(Resist); + // end loop } - // Now go on with a victim's events'n'auras - // Not much to do if no flags are set or there is no victim - if(pVictim && pVictim->isAlive() && procVictim) + data << (uint8)TargetState; + data << (uint32)0; + data << (uint32)0; + + if(HitInfo & HITINFO_BLOCK) { - // processing auras that not generate casts at proc event before auras that generate casts to prevent proc aura added at prev. proc aura execute in set - pVictim->ProcDamageAndSpellFor(true,this,procVictim,victimProcEffectAuraTypes,attType,procSpell, damage, damageSchoolMask); - pVictim->ProcDamageAndSpellFor(true,this,procVictim,victimProcCastAuraTypes,attType,procSpell, damage, damageSchoolMask); + data << uint32(BlockedAmount); } -} -void Unit::CastMeleeProcDamageAndSpell(Unit* pVictim, uint32 damage, SpellSchoolMask damageSchoolMask, WeaponAttackType attType, MeleeHitOutcome outcome, SpellEntry const *spellCasted, bool isTriggeredSpell) -{ - if(!pVictim) - return; - - uint32 procAttacker = PROC_FLAG_NONE; - uint32 procVictim = PROC_FLAG_NONE; - - switch(outcome) + if(HitInfo & HITINFO_UNK3) { - case MELEE_HIT_EVADE: - return; - case MELEE_HIT_MISS: - if(attType == BASE_ATTACK || attType == OFF_ATTACK) - { - procAttacker = PROC_FLAG_MISS; - } - break; - case MELEE_HIT_BLOCK_CRIT: - case MELEE_HIT_CRIT: - if(spellCasted && attType == BASE_ATTACK) - { - procAttacker |= PROC_FLAG_CRIT_SPELL; - procVictim |= PROC_FLAG_STRUCK_CRIT_SPELL; - if ( outcome == MELEE_HIT_BLOCK_CRIT ) - { - procVictim |= PROC_FLAG_BLOCK; - procAttacker |= PROC_FLAG_TARGET_BLOCK; - } - } - else if(attType == BASE_ATTACK || attType == OFF_ATTACK) - { - procAttacker = PROC_FLAG_HIT_MELEE | PROC_FLAG_CRIT_MELEE; - procVictim = PROC_FLAG_STRUCK_MELEE | PROC_FLAG_STRUCK_CRIT_MELEE; - } - else - { - procAttacker = PROC_FLAG_HIT_RANGED | PROC_FLAG_CRIT_RANGED; - procVictim = PROC_FLAG_STRUCK_RANGED | PROC_FLAG_STRUCK_CRIT_RANGED; - } - break; - case MELEE_HIT_PARRY: - procAttacker = PROC_FLAG_TARGET_DODGE_OR_PARRY; - procVictim = PROC_FLAG_PARRY; - break; - case MELEE_HIT_BLOCK: - procAttacker = PROC_FLAG_TARGET_BLOCK; - procVictim = PROC_FLAG_BLOCK; - break; - case MELEE_HIT_DODGE: - procAttacker = PROC_FLAG_TARGET_DODGE_OR_PARRY; - procVictim = PROC_FLAG_DODGE; - break; - case MELEE_HIT_CRUSHING: - if(attType == BASE_ATTACK || attType == OFF_ATTACK) - { - procAttacker = PROC_FLAG_HIT_MELEE | PROC_FLAG_CRIT_MELEE; - procVictim = PROC_FLAG_STRUCK_MELEE | PROC_FLAG_STRUCK_CRIT_MELEE; - } - else - { - procAttacker = PROC_FLAG_HIT_RANGED | PROC_FLAG_CRIT_RANGED; - procVictim = PROC_FLAG_STRUCK_RANGED | PROC_FLAG_STRUCK_CRIT_RANGED; - } - break; - default: - if(attType == BASE_ATTACK || attType == OFF_ATTACK) - { - procAttacker = PROC_FLAG_HIT_MELEE; - procVictim = PROC_FLAG_STRUCK_MELEE; - } - else - { - procAttacker = PROC_FLAG_HIT_RANGED; - procVictim = PROC_FLAG_STRUCK_RANGED; - } - break; + data << uint32(0); } - if(damage > 0) - procVictim |= PROC_FLAG_TAKE_DAMAGE; + if(HitInfo & HITINFO_UNK1) + { + data << uint32(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + data << float(0); + for(uint8 i = 0; i < 5; ++i) + { + data << float(0); + data << float(0); + } + data << uint32(0); + } - if(procAttacker != PROC_FLAG_NONE || procVictim != PROC_FLAG_NONE) - ProcDamageAndSpell(pVictim, procAttacker, procVictim, damage, damageSchoolMask, spellCasted, isTriggeredSpell, attType); -}*/ + SendMessageToSet( &data, true ); +} bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 /*procFlag*/, uint32 /*procEx*/, uint32 cooldown) { @@ -5284,7 +4678,8 @@ bool Unit::HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const * procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown) { SpellEntry const *dummySpell = triggeredByAura->GetSpellProto (); - uint32 effIndex = triggeredByAura->GetEffIndex (); + uint32 effIndex = triggeredByAura->GetEffIndex(); + int32 triggerAmount = triggeredByAura->GetModifier()->m_amount; Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; @@ -5299,7 +4694,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu { switch (dummySpell->Id) { - // Eye of Eye + // Eye for an Eye case 9799: case 25988: { @@ -5308,7 +4703,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; // return damage % to attacker but < 50% own total health - basepoints0 = triggeredByAura->GetModifier()->m_amount*int32(damage)/100; + basepoints0 = triggerAmount*int32(damage)/100; if(basepoints0 > GetMaxHealth()/2) basepoints0 = GetMaxHealth()/2; @@ -5337,15 +4732,14 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu if (!procSpell || procSpell->Id == 24659) return false; // Need remove one 24659 aura - RemoveSingleAuraFromStack(24659, 0); - RemoveSingleAuraFromStack(24659, 1); + RemoveSingleSpellAurasFromStack(24659); return true; } // Restless Strength case 24661: { // Need remove one 24662 aura - RemoveSingleAuraFromStack(24662, 0); + RemoveSingleSpellAurasFromStack(24662); return true; } // Adaptive Warding (Frostfire Regalia set) @@ -5361,7 +4755,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu { if(SpellEntry const* iterSpellProto = (*iter)->GetSpellProto()) { - if(iterSpellProto->SpellFamilyName==SPELLFAMILY_MAGE && (iterSpellProto->SpellFamilyFlags & 0x10000000)) + if(iterSpellProto->SpellFamilyName==SPELLFAMILY_MAGE && (iterSpellProto->SpellFamilyFlags[0] & 0x10000000)) { found=true; break; @@ -5419,7 +4813,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu if(!target) return false; - basepoints0 = int32(damage * 2.5f); // manaregen triggered_spell_id = 34650; break; } @@ -5427,7 +4820,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu case 33493: { // Cast finish spell at last charge - if (triggeredByAura->m_procCharges > 1) + if (triggeredByAura->GetAuraCharges() > 1) return false; target = this; @@ -5627,6 +5020,47 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } return false; } + // Living Seed + case 48504: + { + triggered_spell_id = 48503; + basepoints0 = triggerAmount; + target = this; + break; + } + // Vampiric Touch (generic, used by some boss) + case 52723: + case 60501: + { + triggered_spell_id = 52724; + basepoints0 = damage / 2; + target = this; + break; + } + // Divine purpose + case 31871: + case 31872: + { + // Roll chane + if (!roll_chance_i(triggerAmount)) + return false; + + // Remove any stun effect on target + AuraMap& Auras = pVictim->GetAuras(); + for(AuraMap::iterator iter = Auras.begin(); iter != Auras.end();) + { + SpellEntry const *spell = iter->second->GetSpellProto(); + if( spell->Mechanic == MECHANIC_STUN || + spell->EffectMechanic[iter->second->GetEffIndex()] == MECHANIC_STUN) + { + pVictim->RemoveAurasDueToSpell(spell->Id); + iter = Auras.begin(); + } + else + ++iter; + } + return true; + } } break; } @@ -5639,7 +5073,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; // mana reward - basepoints0 = (triggeredByAura->GetModifier()->m_amount * GetMaxPower(POWER_MANA) / 100); + basepoints0 = (triggerAmount * GetMaxPower(POWER_MANA) / 100); target = this; triggered_spell_id = 29442; break; @@ -5651,7 +5085,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; // mana cost save - basepoints0 = procSpell->manaCost * triggeredByAura->GetModifier()->m_amount/100; + int32 cost = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100; + basepoints0 = cost * triggerAmount/100; if( basepoints0 <=0 ) return false; @@ -5659,8 +5094,45 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 29077; break; } + // Hot Streak + if (dummySpell->SpellIconID == 2999) + { + if (effIndex!=0) + return true; + Aura *counter = GetAura(triggeredByAura->GetId(), 1); + if (!counter) + return true; + + // Count spell criticals in a row in second aura + Modifier *mod = counter->GetModifier(); + if (procEx & PROC_EX_CRITICAL_HIT) + { + mod->m_amount *=2; + if (mod->m_amount < 100) // not enough + return true; + // Crititcal counted -> roll chance + if (roll_chance_i(triggerAmount)) + CastSpell(this, 48108, true, castItem, triggeredByAura); + } + mod->m_amount = 25; + return true; + } + // Burnout + if (dummySpell->SpellIconID == 2998) + { + if(!procSpell) + return false; + + int32 cost = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100; + basepoints0 = cost * triggerAmount/100; + if( basepoints0 <=0 ) + return false; + triggered_spell_id = 44450; + target = this; + break; + } // Incanter's Regalia set (add trigger chance to Mana Shield) - if (dummySpell->SpellFamilyFlags & 0x0000000000008000LL) + if (dummySpell->SpellFamilyFlags[0] & 0x8000) { if(GetTypeId() != TYPEID_PLAYER) return false; @@ -5697,7 +5169,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu case 11129: { //last charge and crit - if (triggeredByAura->m_procCharges <= 1 && (procEx & PROC_EX_CRITICAL_HIT) ) + if (triggeredByAura->GetAuraCharges() <= 1 && (procEx & PROC_EX_CRITICAL_HIT) ) { RemoveAurasDueToSpell(28682); //-> remove Combustion auras return true; // charge counting (will removed) @@ -5712,7 +5184,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu case SPELLFAMILY_WARRIOR: { // Retaliation - if(dummySpell->SpellFamilyFlags==0x0000000800000000LL) + if(dummySpell->SpellFamilyFlags.IsEqual(0, 0x8, 0)) { // check attack comes not from behind if (!HasInArc(M_PI, pVictim)) @@ -5721,26 +5193,21 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 22858; break; } - else if (dummySpell->SpellIconID == 1697) // Second Wind + // Second Wind + if (dummySpell->SpellIconID == 1697) { // only for spells and hit/crit (trigger start always) and not start from self casted spells (5530 Mace Stun Effect for example) if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim) return false; // Need stun or root mechanic - if (procSpell->Mechanic != MECHANIC_ROOT && procSpell->Mechanic != MECHANIC_STUN) - { - int32 i; - for (i=0; i<3; i++) - if (procSpell->EffectMechanic[i] == MECHANIC_ROOT || procSpell->EffectMechanic[i] == MECHANIC_STUN) - break; - if (i == 3) - return false; - } + if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_ROOT)|(1<<MECHANIC_STUN)))) + return false; switch (dummySpell->Id) { case 29838: triggered_spell_id=29842; break; case 29834: triggered_spell_id=29841; break; + case 42770: triggered_spell_id=42771; break; default: sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (SW)",dummySpell->Id); return false; @@ -5749,12 +5216,19 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu target = this; break; } + // Damage Shield + if (dummySpell->SpellIconID == 3214) + { + triggered_spell_id = 59653; + basepoints0 = GetShieldBlockValue() * triggerAmount / 100; + break; + } break; } case SPELLFAMILY_WARLOCK: { // Seed of Corruption - if (dummySpell->SpellFamilyFlags & 0x0000001000000000LL) + if (dummySpell->SpellFamilyFlags[1] & 0x00000010) { Modifier* mod = triggeredByAura->GetModifier(); // if damage is more than need or target die from damage deal finish spell @@ -5798,6 +5272,16 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu mod->m_amount-=damage; return true; } + // Fel Synergy + if (dummySpell->SpellIconID == 3222) + { + target = GetPet(); + if (!target) + return false; + triggered_spell_id = 54181; + basepoints0 = damage * triggerAmount / 100; + break; + } switch(dummySpell->Id) { // Nightfall @@ -5814,7 +5298,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu case 30296: { // health - basepoints0 = int32(damage*triggeredByAura->GetModifier()->m_amount/100); + basepoints0 = int32(damage*triggerAmount/100); target = this; triggered_spell_id = 30294; break; @@ -5833,7 +5317,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; // heal amount - basepoints0 = damage * triggeredByAura->GetModifier()->m_amount/100; + basepoints0 = damage * triggerAmount/100; triggered_spell_id = 37382; break; } @@ -5849,7 +5333,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu case SPELLFAMILY_PRIEST: { // Vampiric Touch - if( dummySpell->SpellFamilyFlags & 0x0000040000000000LL ) + if( dummySpell->SpellFamilyFlags[1] & 0x00000400 ) { if(!pVictim || !pVictim->isAlive()) return false; @@ -5859,10 +5343,17 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; // energize amount - basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/100; + basepoints0 = triggerAmount*damage/100; pVictim->CastCustomSpell(pVictim,34919,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); return true; // no hidden cooldown } + // Divine Aegis + if (dummySpell->SpellIconID == 2820) + { + basepoints0 = damage * triggerAmount/100; + triggered_spell_id = 47753; + break; + } switch(dummySpell->Id) { // Vampiric Embrace @@ -5876,18 +5367,19 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; // heal amount - basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/100; - pVictim->CastCustomSpell(pVictim,15290,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); + int32 team = triggerAmount*damage/500; + int32 self = triggerAmount*damage/100 - team; + pVictim->CastCustomSpell(pVictim,15290,&team,&self,NULL,true,castItem,triggeredByAura); return true; // no hidden cooldown } // Priest Tier 6 Trinket (Ashtongue Talisman of Acumen) case 40438: { // Shadow Word: Pain - if( procSpell->SpellFamilyFlags & 0x0000000000008000LL ) + if( procSpell->SpellFamilyFlags[0] & 0x8000 ) triggered_spell_id = 40441; // Renew - else if( procSpell->SpellFamilyFlags & 0x0000000000000010LL ) + else if( procSpell->SpellFamilyFlags[0] & 0x10 ) triggered_spell_id = 40440; else return false; @@ -5911,12 +5403,12 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; // heal amount - basepoints0 = int32(damage * 2 / 100); + basepoints0 = damage * triggerAmount/100; target = this; triggered_spell_id = 39373; break; } - // Vestments of Faith (Priest Tier 3) - 4 pieces bonus + // Greater Heal (Vestments of Faith (Priest Tier 3) - 4 pieces bonus) case 28809: { triggered_spell_id = 28810; @@ -5959,19 +5451,19 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu float chance; // Starfire - if( procSpell->SpellFamilyFlags & 0x0000000000000004LL ) + if( procSpell->SpellFamilyFlags[0] & 0x4 ) { triggered_spell_id = 40445; chance = 25.f; } // Rejuvenation - else if( procSpell->SpellFamilyFlags & 0x0000000000000010LL ) + else if( procSpell->SpellFamilyFlags[0] & 0x10 ) { triggered_spell_id = 40446; chance = 25.f; } // Mangle (cat/bear) - else if( procSpell->SpellFamilyFlags & 0x0000044000000000LL ) + else if( procSpell->SpellFamilyFlags[1] & 0x00000440) { triggered_spell_id = 40452; chance = 40.f; @@ -5993,6 +5485,39 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu break; } } + // Eclipse + if (dummySpell->SpellIconID == 2856) + { + if (!procSpell) + return false; + // Only 0 aura can proc + if (effIndex!=0) + return true; + // Wrath crit + if (procSpell->SpellFamilyFlags[0] & 0x1) + { + if (!roll_chance_i(60)) + return false; + triggered_spell_id = 48518; + target = this; + break; + } + // Starfire crit + if (procSpell->SpellFamilyFlags[0] & 0x4) + { + triggered_spell_id = 48517; + target = this; + break; + } + return false; + } + // Living Seed + else if (dummySpell->SpellIconID == 2860) + { + triggered_spell_id = 48504; + basepoints0 = triggerAmount * damage / 100; + break; + } break; } case SPELLFAMILY_ROGUE: @@ -6010,19 +5535,39 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu break; } } + // Cut to the Chase + if( dummySpell->SpellIconID == 2909 ) + { + // "refresh your Slice and Dice duration to its 5 combo point maximum" + // lookup Slice and Dice + AuraList const& sd = GetAurasByType(SPELL_AURA_MOD_HASTE); + for(AuraList::const_iterator itr = sd.begin(); itr != sd.end(); ++itr) + { + SpellEntry const *spellProto = (*itr)->GetSpellProto(); + if( spellProto->SpellFamilyName == SPELLFAMILY_ROGUE && + spellProto->SpellFamilyFlags[0] & 0x40000) + { + (*itr)->SetAuraMaxDuration(GetSpellMaxDuration(spellProto)); + (*itr)->RefreshAura(); + return true; + } + } + return false; + } + // Deadly Brew + if( dummySpell->SpellIconID == 2963 ) + { + triggered_spell_id = 25809; + break; + } // Quick Recovery if( dummySpell->SpellIconID == 2116 ) { if(!procSpell) return false; - // only rogue's finishing moves (maybe need additional checks) - if( procSpell->SpellFamilyName!=SPELLFAMILY_ROGUE || - (procSpell->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE__FINISHING_MOVE) == 0) - return false; - // energy cost save - basepoints0 = procSpell->manaCost * triggeredByAura->GetModifier()->m_amount/100; + basepoints0 = procSpell->manaCost * triggerAmount/100; if(basepoints0 <= 0) return false; @@ -6041,7 +5586,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; // mana cost save - basepoints0 = procSpell->manaCost * 40/100; + int32 mana = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100; + basepoints0 = mana * 40/100; if(basepoints0 <= 0) return false; @@ -6049,75 +5595,93 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 34720; break; } + // Hunting Party + if ( dummySpell->SpellIconID == 3406 ) + { + triggered_spell_id = 57669; + target = this; + break; + } + // Lock and Load + if ( dummySpell->SpellIconID == 3579 ) + { + // Proc only from periodic (from trap activation proc another aura of this spell) + if (!(procFlag & PROC_FLAG_ON_DO_PERIODIC) || !roll_chance_i(triggerAmount)) + return false; + triggered_spell_id = 56453; + target = this; + break; + } + // Rapid Recuperation + if ( dummySpell->SpellIconID == 3560 ) + { + // This effect only from Rapid Killing (mana regen) + if (!(procSpell->SpellFamilyFlags[1] & 0x01000000)) + return false; + triggered_spell_id = 56654; + target = this; + break; + } break; } case SPELLFAMILY_PALADIN: { - // Seal of Righteousness - melee proc dummy - if (dummySpell->SpellFamilyFlags&0x000000008000000LL && triggeredByAura->GetEffIndex()==0) + // Seal of Righteousness - melee proc dummy (addition ${$MWS*(0.022*$AP+0.044*$SPH)} damage) + if (dummySpell->SpellFamilyFlags[0]&0x8000000 && effIndex==0) { - if(GetTypeId() != TYPEID_PLAYER) - return false; - - uint32 spellId; - switch (triggeredByAura->GetId()) - { - case 21084: spellId = 25742; break; // Rank 1 - case 20287: spellId = 25740; break; // Rank 2 - case 20288: spellId = 25739; break; // Rank 3 - case 20289: spellId = 25738; break; // Rank 4 - case 20290: spellId = 25737; break; // Rank 5 - case 20291: spellId = 25736; break; // Rank 6 - case 20292: spellId = 25735; break; // Rank 7 - case 20293: spellId = 25713; break; // Rank 8 - case 27155: spellId = 27156; break; // Rank 9 - default: - sLog.outError("Unit::HandleDummyAuraProc: non handled possibly SoR (Id = %u)", triggeredByAura->GetId()); - return false; - } - Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); - float speed = (item ? item->GetProto()->Delay : BASE_ATTACK_TIME)/1000.0f; - - float damageBasePoints; - if(item && item->GetProto()->InventoryType == INVTYPE_2HWEAPON) - // two hand weapon - damageBasePoints=1.20f*triggeredByAura->GetModifier()->m_amount * 1.2f * 1.03f * speed/100.0f + 1; - else - // one hand weapon/no weapon - damageBasePoints=0.85f*ceil(triggeredByAura->GetModifier()->m_amount * 1.2f * 1.03f * speed/100.0f) - 1; - - int32 damagePoint = int32(damageBasePoints + 0.03f * (GetWeaponDamageRange(BASE_ATTACK,MINDAMAGE)+GetWeaponDamageRange(BASE_ATTACK,MAXDAMAGE))/2.0f) + 1; - - // apply damage bonuses manually - if(damagePoint >= 0) - damagePoint = SpellDamageBonus(pVictim, dummySpell, damagePoint, SPELL_DIRECT_DAMAGE); - - CastCustomSpell(pVictim,spellId,&damagePoint,NULL,NULL,true,NULL, triggeredByAura); - return true; // no hidden cooldown + triggered_spell_id = 25742; + float ap = GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = SpellBaseDamageBonus(SPELL_SCHOOL_MASK_HOLY) + + SpellBaseDamageBonusForVictim(SPELL_SCHOOL_MASK_HOLY, pVictim); + basepoints0 = GetAttackTime(BASE_ATTACK) * int32(ap*0.022f + 0.044f * holy) / 1000; + break; } - // Seal of Blood do damage trigger - if(dummySpell->SpellFamilyFlags & 0x0000040000000000LL) + // Sacred Shield + if (dummySpell->SpellFamilyFlags[1]&0x00080000) { - switch(triggeredByAura->GetEffIndex()) - { - case 0: - triggered_spell_id = 31893; - break; - case 1: - { - // damage - damage += CalculateDamage(BASE_ATTACK, false) * 35 / 100; // add spell damage from prev effect (35%) - basepoints0 = triggeredByAura->GetModifier()->m_amount * damage / 100; - - target = this; - triggered_spell_id = 32221; - break; - } - } + triggered_spell_id = 58597; + target = this; + break; + } + // Righteous Vengeance + if (dummySpell->SpellIconID == 3025) + { + // 4 damage tick + basepoints0 = triggerAmount*damage/400; + triggered_spell_id = 61840; + break; + } + // Sheath of Light + if (dummySpell->SpellIconID == 3030) + { + // 4 healing tick + basepoints0 = triggerAmount*damage/400; + triggered_spell_id = 54203; + break; } - switch(dummySpell->Id) { + // Judgement of Light + case 20185: + { + // Get judgement caster + Unit *caster = triggeredByAura->GetCaster(); + if (!caster) + return false; + float ap = caster->GetTotalAttackPowerValue(BASE_ATTACK); + int32 holy = caster->SpellBaseDamageBonus(SPELL_SCHOOL_MASK_HOLY) + + caster->SpellBaseDamageBonusForVictim(SPELL_SCHOOL_MASK_HOLY, this); + basepoints0 = int32(ap*0.10f + 0.10f*holy); + pVictim->CastCustomSpell(pVictim, 20267, &basepoints0, 0, 0, true, 0, triggeredByAura); + return true; + } + // Judgement of Wisdom + case 20186: + { + if (pVictim->getPowerType() == POWER_MANA) + pVictim->CastSpell(pVictim, 20268, true, 0, triggeredByAura); + return true; + } // Holy Power (Redemption Armor set) case 28789: { @@ -6149,7 +5713,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } break; } - //Seal of Vengeance + // Seal of Vengeance (damage calc on apply aura) case 31801: { if(effIndex != 0) // effect 1,2 used by seal unleashing code @@ -6158,7 +5722,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 31803; break; } - // Spiritual Att. + // Spiritual Attunement case 31785: case 33776: { @@ -6167,11 +5731,45 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; // heal amount - basepoints0 = triggeredByAura->GetModifier()->m_amount*damage/100; + basepoints0 = triggerAmount*damage/100; target = this; triggered_spell_id = 31786; break; } + // Seal of Blood do damage trigger + case 31892: + { + if (effIndex == 0) // 0 effect - is proc on enemy + triggered_spell_id = 31893; + else if (effIndex == 1) // 1 effect - is proc on self + { + // add spell damage from prev effect (27%) + damage += CalculateDamage(BASE_ATTACK, false) * 27 / 100; + basepoints0 = triggerAmount * damage / 100; + target = this; + triggered_spell_id = 32221; + } + else + return true; + break; + } + // Seal of the Martyr do damage trigger + case 53720: + { + if (effIndex == 0) // 0 effect - is proc on enemy + triggered_spell_id = 53719; + else if (effIndex == 1) // 1 effect - is proc on self + { + // add spell damage from prev effect (27%) + damage += CalculateDamage(BASE_ATTACK, false) * 27 / 100; + basepoints0 = triggerAmount * damage / 100; + target = this; + triggered_spell_id = 53718; + } + else + return true; + break; + } // Paladin Tier 6 Trinket (Ashtongue Talisman of Zeal) case 40470: { @@ -6181,13 +5779,13 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu float chance; // Flash of light/Holy light - if( procSpell->SpellFamilyFlags & 0x00000000C0000000LL) + if( procSpell->SpellFamilyFlags[0] & 0xC0000000) { triggered_spell_id = 40471; chance = 15.f; } // Judgement - else if( procSpell->SpellFamilyFlags & 0x0000000000800000LL ) + else if( procSpell->SpellFamilyFlags[0] & 0x800000 ) { triggered_spell_id = 40472; chance = 50.f; @@ -6200,6 +5798,33 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu break; } + // Glyph of Divinity + case 54939: + { + // Lookup base amount mana restore + for (int i=0; i<3;i++) + if (procSpell->Effect[i] == SPELL_EFFECT_ENERGIZE) + { + int32 mana = procSpell->EffectBasePoints[i]; + CastCustomSpell(this, 54986, 0, &mana, 0, true, castItem, triggeredByAura); + break; + } + return true; + } + // Glyph of Flash of Light + case 54936: + { + triggered_spell_id = 54957; + basepoints0 = triggerAmount*damage/100; + break; + } + // Glyph of Holy Light + case 54937: + { + triggered_spell_id = 54968; + basepoints0 = triggerAmount*damage/100; + break; + } } break; } @@ -6258,14 +5883,19 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu if( cooldown && ((Player*)this)->HasSpellCooldown(dummySpell->Id)) return false; + // Now amount of extra power stored in 1 effect of Enchant spell + // Get it by item enchant id uint32 spellId; switch (castItem->GetEnchantmentId(EnchantmentSlot(TEMP_ENCHANTMENT_SLOT))) { - case 283: spellId = 33757; break; //1 Rank - case 284: spellId = 33756; break; //2 Rank - case 525: spellId = 33755; break; //3 Rank - case 1669:spellId = 33754; break; //4 Rank - case 2636:spellId = 33727; break; //5 Rank + case 283: spellId = 8232; break; // 1 Rank + case 284: spellId = 8235; break; // 2 Rank + case 525: spellId = 10486; break; // 3 Rank + case 1669:spellId = 16362; break; // 4 Rank + case 2636:spellId = 25505; break; // 5 Rank + case 3785:spellId = 58801; break; // 6 Rank + case 3786:spellId = 58803; break; // 7 Rank + case 3787:spellId = 58804; break; // 8 Rank default: { sLog.outError("Unit::HandleDummyAuraProc: non handled item enchantment (rank?) %u for spell id: %u (Windfury)", @@ -6281,7 +5911,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; } - int32 extra_attack_power = CalculateSpellDamage(windfurySpellEntry,0,windfurySpellEntry->EffectBasePoints[0],pVictim); + int32 extra_attack_power = CalculateSpellDamage(windfurySpellEntry, 1, windfurySpellEntry->EffectBasePoints[1], pVictim); // Off-Hand case if ( castItem->GetSlot() == EQUIPMENT_SLOT_OFFHAND ) @@ -6315,17 +5945,17 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return false; float chance; - if (procSpell->SpellFamilyFlags & 0x0000000000000001LL) + if (procSpell->SpellFamilyFlags[0] & 0x1) { triggered_spell_id = 40465; // Lightning Bolt chance = 15.f; } - else if (procSpell->SpellFamilyFlags & 0x0000000000000080LL) + else if (procSpell->SpellFamilyFlags[0] & 0x80) { triggered_spell_id = 40465; // Lesser Healing Wave chance = 10.f; } - else if (procSpell->SpellFamilyFlags & 0x0000001000000000LL) + else if (procSpell->SpellFamilyFlags[1] & 0x00000010) { triggered_spell_id = 40466; // Stormstrike chance = 50.f; @@ -6339,20 +5969,69 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu target = this; break; } + // Glyph of Healing Wave + case 55440: + { + // Not proc from self heals + if (this==pVictim) + return false; + basepoints0 = triggerAmount * damage / 100; + target = this; + triggered_spell_id = 55533; + break; + } + // Spirit Hunt + case 58877: + { + // Cast on owner + target = GetOwner(); + if(!target) + return false; + basepoints0 = triggerAmount * damage / 100; + triggered_spell_id = 58879; + break; + } + } + // Ancestral Awakening + if (dummySpell->SpellIconID == 2018) + { + // TODO: frite dummy fot triggered spell + triggered_spell_id = 52759; + basepoints0 = triggerAmount * damage / 100; + target = this; + break; } - // Earth Shield - if(dummySpell->SpellFamilyFlags==0x40000000000LL) + if(dummySpell->SpellFamilyFlags[1] & 0x00000400) { - if(GetTypeId() != TYPEID_PLAYER) - return false; - - // heal - basepoints0 = triggeredByAura->GetModifier()->m_amount; + basepoints0 = triggerAmount; target = this; triggered_spell_id = 379; break; } + // Improved Water Shield + if (dummySpell->SpellIconID == 2287) + { + // Lesser Healing Wave need aditional 60% roll + if (procSpell->SpellFamilyFlags[0] & 0x80 && !roll_chance_i(60)) + return false; + // lookup water shield + AuraList const& vs = GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL); + for(AuraList::const_iterator itr = vs.begin(); itr != vs.end(); ++itr) + { + if( (*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && + (*itr)->GetSpellProto()->SpellFamilyFlags[1] & 0x00000020) + { + uint32 spell = (*itr)->GetSpellProto()->EffectTriggerSpell[(*itr)->GetEffIndex()]; + CastSpell(this, spell, true, castItem, triggeredByAura); + if ((*itr)->DropAuraCharge()) + RemoveAurasDueToSpell((*itr)->GetId()); + return true; + } + } + return false; + break; + } // Lightning Overload if (dummySpell->SpellIconID == 2018) // only this spell have SpellFamily Shaman SpellIconID == 2018 and dummy aura { @@ -6380,6 +6059,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu case 15208: spellId = 45294; break; // Rank 10 case 25448: spellId = 45295; break; // Rank 11 case 25449: spellId = 45296; break; // Rank 12 + case 49237: spellId = 49239; break; // Rank 13 + case 49238: spellId = 49240; break; // Rank 14 // Chain Lightning case 421: spellId = 45297; break; // Rank 1 case 930: spellId = 45298; break; // Rank 2 @@ -6387,31 +6068,26 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu case 10605: spellId = 45300; break; // Rank 4 case 25439: spellId = 45301; break; // Rank 5 case 25442: spellId = 45302; break; // Rank 6 + case 49268: spellId = 49270; break; // Rank 7 + case 49269: spellId = 49271; break; // Rank 8 default: sLog.outError("Unit::HandleDummyAuraProc: non handled spell id: %u (LO)", procSpell->Id); return false; } // No thread generated mod + // TODO: exist special flag in spell attributes for this, need found and use! SpellModifier *mod = new SpellModifier; mod->op = SPELLMOD_THREAT; mod->value = -100; mod->type = SPELLMOD_PCT; mod->spellId = dummySpell->Id; - mod->effectId = 0; - mod->lastAffected = NULL; - mod->mask = 0x0000000000000003LL; - mod->charges = 0; + mod->mask[0] = 0x3; ((Player*)this)->AddSpellMod(mod, true); // Remove cooldown (Chain Lightning - have Category Recovery time) - if (procSpell->SpellFamilyFlags & 0x0000000000000002LL) + if (procSpell->SpellFamilyFlags[0] & 0x2) ((Player*)this)->RemoveSpellCooldown(spellId); - // Hmmm.. in most case spells already set half basepoints but... - // Lightning Bolt (2-10 rank) have full basepoint and half bonus from level - // As on wiki: - // BUG: Rank 2 to 10 (and maybe 11) of Lightning Bolt will proc another Bolt with FULL damage (not halved). This bug is known and will probably be fixed soon. - // So - no add changes :) CastSpell(pVictim, spellId, true, castItem, triggeredByAura); ((Player*)this)->AddSpellMod(mod, false); @@ -6421,6 +6097,117 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return true; } + // Static Shock + if(dummySpell->SpellIconID == 3059) + { + // lookup Lightning Shield + AuraList const& vs = GetAurasByType(SPELL_AURA_PROC_TRIGGER_SPELL); + for(AuraList::const_iterator itr = vs.begin(); itr != vs.end(); ++itr) + { + if( (*itr)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_SHAMAN && + (*itr)->GetSpellProto()->SpellFamilyFlags[0] & 0x400) + { + uint32 spell = 0; + switch ((*itr)->GetId()) + { + case 324: spell = 26364; break; + case 325: spell = 26365; break; + case 905: spell = 26366; break; + case 945: spell = 26367; break; + case 8134: spell = 26369; break; + case 10431: spell = 26370; break; + case 10432: spell = 26363; break; + case 25469: spell = 26371; break; + case 25472: spell = 26372; break; + case 49280: spell = 49278; break; + case 49281: spell = 49279; break; + default: + return false; + } + CastSpell(this, spell, true, castItem, triggeredByAura); + if ((*itr)->DropAuraCharge()) + RemoveAurasDueToSpell((*itr)->GetId()); + return true; + } + } + return false; + break; + } + break; + } + case SPELLFAMILY_DEATHKNIGHT: + { + // Blood Aura + if (dummySpell->SpellIconID == 2636) + { + if (GetTypeId() != TYPEID_PLAYER || !((Player*)this)->isHonorOrXPTarget(pVictim)) + return false; + basepoints0 = triggerAmount * damage / 100; + triggered_spell_id = 53168; + break; + } + // Butchery + if (dummySpell->SpellIconID == 2664) + { + basepoints0 = triggerAmount; + triggered_spell_id = 50163; + target = this; + break; + } + // Dancing Rune Weapon + if (dummySpell->Id == 49028) + { + // 1 dummy aura for dismiss rune blade + if (effIndex!=2) + return false; + // TODO: wite script for this "fights on its own, doing the same attacks" + // NOTE: Trigger here on every attack and spell cast + return false; + } + // Mark of Blood + if (dummySpell->Id == 49005) + { + // TODO: need more info (cooldowns/PPM) + triggered_spell_id = 50424; + break; + } + // Vendetta + if (dummySpell->SpellFamilyFlags[0] & 0x10000) + { + basepoints0 = triggerAmount * GetMaxHealth() / 100; + triggered_spell_id = 50181; + target = this; + break; + } + // Necrosis + if (dummySpell->SpellIconID == 2709) + { + basepoints0 = triggerAmount * damage / 100; + triggered_spell_id = 51460; + break; + } + // Runic Power Back on Snare/Root + if (dummySpell->Id == 61257) + { + // only for spells and hit/crit (trigger start always) and not start from self casted spells + if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim) + return false; + // Need snare or root mechanic + if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_ROOT)|(1<<MECHANIC_SNARE)))) + return false; + triggered_spell_id = 61258; + target = this; + break; + } + // Wandering Plague + if (dummySpell->SpellIconID == 1614) + { + if (!roll_chance_f(GetUnitCriticalChance(BASE_ATTACK, pVictim))) + return false; + basepoints0 = triggerAmount * damage / 100; + triggered_spell_id = 50526; + break; + } break; } default: @@ -6456,1172 +6243,518 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu return true; } -/* -bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlags,WeaponAttackType attackType, uint32 cooldown) + +bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlags, uint32 procEx, uint32 cooldown) { + // Get triggered aura spell info SpellEntry const* auraSpellInfo = triggeredByAura->GetSpellProto(); + // Basepoints of trigger aura + int32 triggerAmount = triggeredByAura->GetModifier()->m_amount; + + // Set trigger spell id, target, custom basepoints + uint32 trigger_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()]; + Unit* target = NULL; + int32 basepoints0 = 0; + + if(triggeredByAura->GetModifier()->m_auraname == SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE) + basepoints0 = triggerAmount; + Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; - uint32 triggered_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()]; - Unit* target = !(procFlags & PROC_FLAG_HEAL) && IsPositiveSpell(triggered_spell_id) ? this : pVictim; - int32 basepoints0 = 0; - - switch(auraSpellInfo->SpellFamilyName) + // Try handle uncnown trigger spells + if (sSpellStore.LookupEntry(trigger_spell_id)==NULL) { - case SPELLFAMILY_GENERIC: - { - switch(auraSpellInfo->Id) - { - // Aegis of Preservation - case 23780: - //Aegis Heal (instead non-existed triggered spell) - triggered_spell_id = 23781; - target = this; - break; - // Elune's Touch (moonkin mana restore) - case 24905: - { - // Elune's Touch (instead non-existed triggered spell) - triggered_spell_id = 33926; - basepoints0 = int32(0.3f * GetTotalAttackPowerValue(BASE_ATTACK)); - target = this; + switch (auraSpellInfo->SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + //if (auraSpellInfo->Id==59532) // Abandon Passengers on Poly + //if (auraSpellInfo->Id==54775) // Abandon Vehicle on Poly + //if (auraSpellInfo->Id==34082) // Advantaged State (DND) + if (auraSpellInfo->Id == 23780) // Aegis of Preservation (Aegis of Preservation trinket) + trigger_spell_id = 23781; + //else if (auraSpellInfo->Id==43504) // Alterac Valley OnKill Proc Aura + //else if (auraSpellInfo->Id == 48876) // Beast's Mark + //{ + // trigger_spell_id = 48877; + //} + //else if (auraSpellInfo->Id == 59237) // Beast's Mark + //{ + // trigger_spell_id = 59233; + //} + //else if (auraSpellInfo->Id==46939) // Black Bow of the Betrayer + //{ + // trigger_spell_id = 29471; // gain mana + // 27526; // drain mana if possible + //} + //else if (auraSpellInfo->Id==50844) // Blood Mirror + //else if (auraSpellInfo->Id==54476) // Blood Presence + //else if (auraSpellInfo->Id==50689) // Blood Presence (Rank 1) + //else if (auraSpellInfo->Id==37030) // Chaotic Temperament + //else if (auraSpellInfo->Id==52856) // Charge + else if (auraSpellInfo->Id==43820) // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket) + { + // Pct value stored in dummy + basepoints0 = pVictim->GetCreateHealth() * auraSpellInfo->EffectBasePoints[1] / 100; + target = pVictim; break; } - // Enlightenment - case 29601: - { - // only for cast with mana price - if(!procSpell || procSpell->powerType!=POWER_MANA || procSpell->manaCost==0 && procSpell->ManaCostPercentage==0 && procSpell->manaCostPerlevel==0) - return false; - break; // fall through to normal cast - } - // Health Restore - case 33510: + //else if (auraSpellInfo->Id==41248) // Consuming Strikes + // trigger_spell_id = 41249; + //else if (auraSpellInfo->Id==45205) // Copy Offhand Weapon + //else if (auraSpellInfo->Id==57594) // Copy Ranged Weapon + //else if (auraSpellInfo->Id==41054) // Copy Weapon + // trigger_spell_id = 41055; + //else if (auraSpellInfo->Id==45343) // Dark Flame Aura + //else if (auraSpellInfo->Id==47300) // Dark Flame Aura + else if (auraSpellInfo->Id==57345) // Darkmoon Card: Greatness + { + uint32 stat = 0; + // strength + if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 60229;stat = GetStat(STAT_STRENGTH); } + // agility + if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 60233;stat = GetStat(STAT_AGILITY); } + // intellect + if (GetStat(STAT_INTELLECT)> stat) { trigger_spell_id = 60234;stat = GetStat(STAT_INTELLECT);} + // spirit + if (GetStat(STAT_SPIRIT) > stat) { trigger_spell_id = 60235;stat = GetStat(STAT_SPIRIT); } + } + //else if (auraSpellInfo->Id==31255) // Deadly Swiftness (Rank 1) + //else if (auraSpellInfo->Id==5301) // Defensive State (DND) + //else if (auraSpellInfo->Id==13358) // Defensive State (DND) + //else if (auraSpellInfo->Id==16092) // Defensive State (DND) + //else if (auraSpellInfo->Id==24949) // Defensive State 2 (DND) + //else if (auraSpellInfo->Id==40329) // Demo Shout Sensor + else if (auraSpellInfo->Id == 33896) // Desperate Defense (Stonescythe Whelp, Stonescythe Alpha, Stonescythe Ambusher) + trigger_spell_id = 33898; + //else if (auraSpellInfo->Id==18943) // Double Attack + //else if (auraSpellInfo->Id==19194) // Double Attack + //else if (auraSpellInfo->Id==19817) // Double Attack + //else if (auraSpellInfo->Id==19818) // Double Attack + //else if (auraSpellInfo->Id==22835) // Drunken Rage + // trigger_spell_id = 14822; + /* + else if (auraSpellInfo->SpellIconID==191) // Elemental Response { - // at melee hit call std triggered spell - if(procFlags & PROC_FLAG_HIT_MELEE) - break; // fall through to normal cast - - // Mark of Conquest - else (at range hit) called custom case - triggered_spell_id = 39557; - target = this; - break; + switch (auraSpellInfo->Id && auraSpellInfo->AttributesEx==0) + { + case 34191: + case 34329: + case 34524: + case 34582: + case 36733: + break; + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Elemental Response",auraSpellInfo->Id); + return false; + } + //This generic aura self-triggers a different spell for each school of magic that lands on the wearer: + switch (procSpell->School) + { + case SPELL_SCHOOL_FIRE: trigger_spell_id = 34192; break; + case SPELL_SCHOOL_FROST: trigger_spell_id = 34193; break; + case SPELL_SCHOOL_ARCANE:trigger_spell_id = 34194; break; + case SPELL_SCHOOL_NATURE:trigger_spell_id = 34195; break; + case SPELL_SCHOOL_SHADOW:trigger_spell_id = 34196; break; + case SPELL_SCHOOL_HOLY: trigger_spell_id = 34197; break; + case SPELL_SCHOOL_NORMAL:trigger_spell_id = 34198; break; + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u Elemental Response wrong school",auraSpellInfo->Id); + return false; + } } - // Shaleskin - case 36576: - return true; // nothing to do - // Forgotten Knowledge (Blade of Wizardry) - case 38319: - // only for harmful enemy targeted spell - if(!pVictim || pVictim==this || !procSpell || IsPositiveSpell(procSpell->Id)) - return false; - break; // fall through to normal cast - // Aura of Wrath (Darkmoon Card: Wrath trinket bonus) - case 39442: - { - // proc only at non-crit hits - if(procFlags & (PROC_FLAG_CRIT_MELEE|PROC_FLAG_CRIT_RANGED|PROC_FLAG_CRIT_SPELL)) - return false; - break; // fall through to normal cast + */ + //else if (auraSpellInfo->Id==40364) // Entangling Roots Sensor + //else if (auraSpellInfo->Id==33207) // Gossip NPC Periodic - Fidget + //else if (auraSpellInfo->Id==50051) // Ethereal Pet Aura + //else if (auraSpellInfo->Id==35321) // Gushing Wound + //else if (auraSpellInfo->Id==38363) // Gushing Wound + //else if (auraSpellInfo->Id==39215) // Gushing Wound + //else if (auraSpellInfo->Id==44527) // Hate Monster (Spar Buddy) (30 sec) + //else if (auraSpellInfo->Id==44819) // Hate Monster (Spar Buddy) (>30% Health) + //else if (auraSpellInfo->Id==44526) // Hate Monster (Spar) (30 sec) + //else if (auraSpellInfo->Id==44820) // Hate Monster (Spar) (<30%) + //else if (auraSpellInfo->Id==49059) // Horde, Hate Monster (Spar Buddy) (>30% Health) + //else if (auraSpellInfo->Id==40250) // Improved Duration + //else if (auraSpellInfo->Id==59288) // Infra-Green Shield + //else if (auraSpellInfo->Id==54072) // Knockback Ball Passive + else if (auraSpellInfo->Id==27522 || auraSpellInfo->Id==40336) + // Mana Drain Trigger + { + // On successful melee or ranged attack gain $29471s1 mana and if possible drain $27526s1 mana from the target. + if (this && this->isAlive()) + CastSpell(this, 29471, true, castItem, triggeredByAura); + if (pVictim && pVictim->isAlive()) + CastSpell(pVictim, 27526, true, castItem, triggeredByAura); + return true; } - // Augment Pain (Timbal's Focusing Crystal trinket bonus) - case 45054: + //else if (auraSpellInfo->Id==55580) // Mana Link + //else if (auraSpellInfo->Id==45903) // Offensive State + //else if (auraSpellInfo->Id==44326) // Pure Energy Passive + //else if (auraSpellInfo->Id==43453) // Rune Ward + //else if (auraSpellInfo->Id== 7137) // Shadow Charge (Rank 1) + //else if (auraSpellInfo->Id==36576) // Shaleskin (Shaleskin Flayer, Shaleskin Ripper) 30023 trigger + //else if (auraSpellInfo->Id==34783) // Spell Reflection + //else if (auraSpellInfo->Id==36096) // Spell Reflection + //else if (auraSpellInfo->Id==57587) // Steal Ranged () + //else if (auraSpellInfo->Id==36207) // Steal Weapon + //else if (auraSpellInfo->Id== 7377) // Take Immune Periodic Damage <Not Working> + //else if (auraSpellInfo->Id==35205) // Vanish + //else if (auraSpellInfo->Id==42730) // Woe Strike + //else if (auraSpellInfo->Id==59735) // Woe Strike + //else if (auraSpellInfo->Id==46146) // [PH] Ahune Spanky Hands + break; + case SPELLFAMILY_MAGE: + if (auraSpellInfo->SpellIconID == 2127) // Blazing Speed { - if(!procSpell) - return false; - - //only periodic damage can trigger spell - bool found = false; - for(int j = 0; j < 3; ++j) + switch (auraSpellInfo->Id) { - if( procSpell->EffectApplyAuraName[j]==SPELL_AURA_PERIODIC_DAMAGE || - procSpell->EffectApplyAuraName[j]==SPELL_AURA_PERIODIC_DAMAGE_PERCENT || - procSpell->EffectApplyAuraName[j]==SPELL_AURA_PERIODIC_LEECH ) - { - found = true; + case 31641: // Rank 1 + case 31642: // Rank 2 + trigger_spell_id = 31643; break; - } + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Blazing Speed",auraSpellInfo->Id); + return false; } - if(!found) - return false; - - break; // fall through to normal cast } - // Evasive Maneuvers (Commendation of Kael'thas) - case 45057: + break; + case SPELLFAMILY_WARRIOR: + if (auraSpellInfo->Id == 50421) // Scent of Blood + trigger_spell_id = 50422; + break; + case SPELLFAMILY_WARLOCK: + { + // Pyroclasm + if (auraSpellInfo->SpellIconID == 1137) { - // damage taken that reduces below 35% health - // does NOT mean you must have been >= 35% before - if (int32(GetHealth())-int32(damage) >= int32(GetMaxHealth()*0.35f)) + if(!pVictim || !pVictim->isAlive() || pVictim == this || procSpell == NULL) + return false; + // Calculate spell tick count for spells + uint32 tick = 1; // Default tick = 1 + + // Hellfire have 15 tick + if (procSpell->SpellFamilyFlags[0]&0x40) + tick = 15; + // Rain of Fire have 4 tick + else if (procSpell->SpellFamilyFlags[0]&0x20) + tick = 4; + else return false; - break; // fall through to normal cast - } - } - switch(triggered_spell_id) - { - // Setup - case 15250: - { - // applied only for main target - if(!pVictim || pVictim != getVictim()) + // Calculate chance = baseChance / tick + float chance = 0; + switch (auraSpellInfo->Id) + { + case 18096: chance = 13.0f / tick; break; + case 18073: chance = 26.0f / tick; break; + } + // Roll chance + if (!roll_chance_f(chance)) return false; - // continue normal case - break; + trigger_spell_id = 18093; } - // Shamanistic Rage triggered spell - case 30824: - basepoints0 = int32(GetTotalAttackPowerValue(BASE_ATTACK)*triggeredByAura->GetModifier()->m_amount/100); - break; - } - break; - } - case SPELLFAMILY_MAGE: - { - switch(auraSpellInfo->SpellIconID) - { - // Blazing Speed - case 2127: - //Blazing Speed (instead non-existed triggered spell) - triggered_spell_id = 31643; - target = this; - break; - } - switch(auraSpellInfo->Id) - { - // Persistent Shield (Scarab Brooch) - case 26467: - basepoints0 = int32(damage * 0.15f); - break; - } - break; - } - case SPELLFAMILY_WARRIOR: - { - //Rampage - if((auraSpellInfo->SpellFamilyFlags & 0x100000) && auraSpellInfo->SpellIconID==2006) - { - //all ranks have effect[0]==AURA (Proc Trigger Spell, non-existed) - //and effect[1]==TriggerSpell - if(auraSpellInfo->Effect[1]!=SPELL_EFFECT_TRIGGER_SPELL) + // Drain Soul + else if (auraSpellInfo->SpellFamilyFlags[0] & 0x4000) { - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u have wrong effect in RM",triggeredByAura->GetSpellProto()->Id); + Unit::AuraList const& mAddFlatModifier = GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER); + for(Unit::AuraList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i) + { + if ((*i)->GetModifier()->m_miscvalue == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellProto()->SpellIconID == 113) + { + int32 value2 = CalculateSpellDamage((*i)->GetSpellProto(),2,(*i)->GetSpellProto()->EffectBasePoints[2],this); + // Drain Soul + CastCustomSpell(this, 18371, &basepoints0, NULL, NULL, true, castItem, triggeredByAura); + break; + } + } + // Not remove charge (aura removed on death in any cases) + // Need for correct work Drain Soul SPELL_AURA_CHANNEL_DEATH_ITEM aura return false; } - triggered_spell_id = auraSpellInfo->EffectTriggerSpell[1]; - break; // fall through to normal cast - } - break; - } - case SPELLFAMILY_WARLOCK: - { - // Pyroclasm - if(auraSpellInfo->SpellFamilyFlags == 0x0000000000000000 && auraSpellInfo->SpellIconID==1137) - { - // last case for Hellfire that damage caster also but don't must stun caster - if( pVictim == this ) - return false; - - // custom chance - float chance = 0; - switch (triggeredByAura->GetId()) + // Nether Protection + else if (auraSpellInfo->SpellIconID == 1985) { - case 18096: chance = 13.0f; break; - case 18073: chance = 26.0f; break; - } - if (!roll_chance_f(chance)) - return false; - - // Pyroclasm (instead non-existed triggered spell) - triggered_spell_id = 18093; - target = pVictim; - break; - } - // Drain Soul - if(auraSpellInfo->SpellFamilyFlags & 0x0000000000004000) - { - bool found = false; - Unit::AuraList const& mAddFlatModifier = GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER); - for(Unit::AuraList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i) - { - //Improved Drain Soul - if ((*i)->GetModifier()->m_miscvalue == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellProto()->SpellIconID == 113) + if (!procSpell) + return false; + switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell))) { - int32 value2 = CalculateSpellDamage((*i)->GetSpellProto(),2,(*i)->GetSpellProto()->EffectBasePoints[2],this); - basepoints0 = value2 * GetMaxPower(POWER_MANA) / 100; - // Drain Soul - CastCustomSpell(this, 18371, &basepoints0, NULL, NULL, true, castItem, triggeredByAura); - break; + case SPELL_SCHOOL_NORMAL: + case SPELL_SCHOOL_HOLY: + return false; // ignore + case SPELL_SCHOOL_FIRE: trigger_spell_id = 54371; break; + case SPELL_SCHOOL_NATURE: trigger_spell_id = 54375; break; + case SPELL_SCHOOL_FROST: trigger_spell_id = 54372; break; + case SPELL_SCHOOL_SHADOW: trigger_spell_id = 54374; break; + case SPELL_SCHOOL_ARCANE: trigger_spell_id = 54373; break; + default: + return false; } } - // Not remove charge (aura removed on death in any cases) - // Need for correct work Drain Soul SPELL_AURA_CHANNEL_DEATH_ITEM aura - return false; + break; } - break; - } - case SPELLFAMILY_PRIEST: - { - //Blessed Recovery - if(auraSpellInfo->SpellFamilyFlags == 0x00000000LL && auraSpellInfo->SpellIconID==1875) + case SPELLFAMILY_PRIEST: { - switch (triggeredByAura->GetSpellProto()->Id) + // Greater Heal Refund + if (auraSpellInfo->Id==37594) + trigger_spell_id = 37595; + // Blessed Recovery + else if (auraSpellInfo->SpellIconID == 1875) { - case 27811: triggered_spell_id = 27813; break; - case 27815: triggered_spell_id = 27817; break; - case 27816: triggered_spell_id = 27818; break; - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in BR",triggeredByAura->GetSpellProto()->Id); - return false; - } - - int32 heal_amount = damage * triggeredByAura->GetModifier()->m_amount / 100; - basepoints0 = heal_amount/3; - target = this; - break; - } - // Shadowguard - if((auraSpellInfo->SpellFamilyFlags & 0x80000000LL) && auraSpellInfo->SpellVisual==7958) - { - switch(triggeredByAura->GetSpellProto()->Id) - { - case 18137: - triggered_spell_id = 28377; break; // Rank 1 - case 19308: - triggered_spell_id = 28378; break; // Rank 2 - case 19309: - triggered_spell_id = 28379; break; // Rank 3 - case 19310: - triggered_spell_id = 28380; break; // Rank 4 - case 19311: - triggered_spell_id = 28381; break; // Rank 5 - case 19312: - triggered_spell_id = 28382; break; // Rank 6 - case 25477: - triggered_spell_id = 28385; break; // Rank 7 - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in SG",triggeredByAura->GetSpellProto()->Id); + switch (auraSpellInfo->Id) + { + case 27811: trigger_spell_id = 27813; break; + case 27815: trigger_spell_id = 27817; break; + case 27816: trigger_spell_id = 27818; break; + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id); return false; + } + basepoints0 = damage * triggerAmount / 100 / 3; + target = this; } - target = pVictim; break; } - break; - } - case SPELLFAMILY_DRUID: - { - switch(auraSpellInfo->Id) + case SPELLFAMILY_DRUID: { - // Leader of the Pack (triggering Improved Leader of the Pack heal) - case 24932: - { - if (triggeredByAura->GetModifier()->m_amount == 0) - return false; - basepoints0 = triggeredByAura->GetModifier()->m_amount * GetMaxHealth() / 100; - triggered_spell_id = 34299; - break; - }; - // Druid Forms Trinket (Druid Tier5 Trinket, triggers different spells per Form) - case 37336: + // Druid Forms Trinket + if (auraSpellInfo->Id==37336) { switch(m_form) { + case FORM_NONE: trigger_spell_id = 37344;break; + case FORM_CAT: trigger_spell_id = 37341;break; case FORM_BEAR: - case FORM_DIREBEAR: - triggered_spell_id=37340; break;// Ursine Blessing - case FORM_CAT: - triggered_spell_id=37341; break;// Feline Blessing - case FORM_TREE: - triggered_spell_id=37342; break;// Slyvan Blessing - case FORM_MOONKIN: - triggered_spell_id=37343; break;// Lunar Blessing - case FORM_NONE: - triggered_spell_id=37344; break;// Cenarion Blessing (for caster form, except FORM_MOONKIN) + case FORM_DIREBEAR: trigger_spell_id = 37340;break; + case FORM_TREE: trigger_spell_id = 37342;break; + case FORM_MOONKIN: trigger_spell_id = 37343;break; default: return false; } - - target = this; - break; } - } - break; - } - case SPELLFAMILY_ROGUE: - { - if(auraSpellInfo->SpellFamilyFlags == 0x0000000000000000LL) - { - switch(auraSpellInfo->SpellIconID) + //else if (auraSpellInfo->Id==40363)// Entangling Roots () + // trigger_spell_id = ????; + // Leader of the Pack + else if (auraSpellInfo->Id == 24932) { - // Combat Potency - case 2260: - { - // skip non offhand attacks - if(attackType!=OFF_ATTACK) - return false; - break; // fall through to normal cast - } + if (triggerAmount == 0) + return false; + basepoints0 = triggerAmount * GetMaxHealth() / 100; + trigger_spell_id = 34299; } + break; } - break; - } - case SPELLFAMILY_PALADIN: - { - if(auraSpellInfo->SpellFamilyFlags == 0x00000000LL) + case SPELLFAMILY_HUNTER: + break; + case SPELLFAMILY_PALADIN: { - switch(auraSpellInfo->Id) + /* + // Blessed Life + if (auraSpellInfo->SpellIconID == 2137) { - // Lightning Capacitor - case 37657: - { - // trinket ProcTriggerSpell but for safe checks for player - if(!castItem || !pVictim || !pVictim->isAlive() || GetTypeId()!=TYPEID_PLAYER) - return false; - - if(((Player*)this)->HasSpellCooldown(37657)) - return false; - - // stacking - CastSpell(this, 37658, true, castItem, triggeredByAura); - // 2.5s cooldown before it can stack again, current system allow 1 sec step in cooldown - ((Player*)this)->AddSpellCooldown(37657,0,time(NULL)+(roll_chance_i(50) ? 2 : 3)); - - // counting - Aura * dummy = GetDummyAura(37658); - if (!dummy) - return false; - - // release at 3 aura in stack - if(dummy->GetStackAmount() <= 2) - return true; // main triggered spell casted anyway - - RemoveAurasDueToSpell(37658); - CastSpell(pVictim, 37661, true, castItem, triggeredByAura); - return true; - } - // Healing Discount - case 37705: - // Healing Trance (instead non-existed triggered spell) - triggered_spell_id = 37706; - target = this; - break; - // HoTs on Heals (Fel Reaver's Piston trinket) - case 38299: + switch (auraSpellInfo->Id) { - // at direct heal effect - if(!procSpell || !IsSpellHaveEffect(procSpell,SPELL_EFFECT_HEAL)) + case 31828: // Rank 1 + case 31829: // Rank 2 + case 31830: // Rank 3 + break; + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Blessed Life", auraSpellInfo->Id); return false; - - // single proc at time - AuraList const& scAuras = GetSingleCastAuras(); - for(AuraList::const_iterator itr = scAuras.begin(); itr != scAuras.end(); ++itr) - if((*itr)->GetId()==triggered_spell_id) - return false; - - // positive cast at victim instead self - target = pVictim; - break; } } - switch(auraSpellInfo->SpellIconID) + */ + // Healing Discount + if (auraSpellInfo->Id==37705) { - case 241: - { - switch(auraSpellInfo->EffectTriggerSpell[0]) - { - //Illumination - case 18350: - { - if(!procSpell) - return false; - - // procspell is triggered spell but we need mana cost of original casted spell - uint32 originalSpellId = procSpell->Id; - - // Holy Shock - if(procSpell->SpellFamilyName == SPELLFAMILY_PALADIN) - { - if(procSpell->SpellFamilyFlags & 0x0001000000000000LL) - { - switch(procSpell->Id) - { - case 25914: originalSpellId = 20473; break; - case 25913: originalSpellId = 20929; break; - case 25903: originalSpellId = 20930; break; - case 27175: originalSpellId = 27174; break; - case 33074: originalSpellId = 33072; break; - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in HShock",procSpell->Id); - return false; - } - } - } - - SpellEntry const *originalSpell = sSpellStore.LookupEntry(originalSpellId); - if(!originalSpell) - { - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu",originalSpellId); - return false; - } - - // percent stored in effect 1 (class scripts) base points - int32 percent = auraSpellInfo->EffectBasePoints[1]+1; - - basepoints0 = originalSpell->manaCost*percent/100; - triggered_spell_id = 20272; - target = this; - break; - } - } - break; - } + trigger_spell_id = 37706; + target = this; } - } - if(auraSpellInfo->SpellFamilyFlags & 0x00080000) - { - switch(auraSpellInfo->SpellIconID) + // Soul Preserver + if (auraSpellInfo->Id==60510) + { + trigger_spell_id = 60515; + target = this; + } + // Illumination + else if (auraSpellInfo->SpellIconID==241) { - //Judgement of Wisdom (overwrite non existing triggered spell call in spell.dbc - case 206: + if(!procSpell) + return false; + // procspell is triggered spell but we need mana cost of original casted spell + uint32 originalSpellId = procSpell->Id; + // Holy Shock heal + if(procSpell->SpellFamilyFlags[1] & 0x00010000) { - if(!pVictim || !pVictim->isAlive()) - return false; - - switch(triggeredByAura->GetSpellProto()->Id) + switch(procSpell->Id) { - case 20186: - triggered_spell_id = 20268; // Rank 1 - break; - case 20354: - triggered_spell_id = 20352; // Rank 2 - break; - case 20355: - triggered_spell_id = 20353; // Rank 3 - break; - case 27164: - triggered_spell_id = 27165; // Rank 4 - break; + case 25914: originalSpellId = 20473; break; + case 25913: originalSpellId = 20929; break; + case 25903: originalSpellId = 20930; break; + case 27175: originalSpellId = 27174; break; + case 33074: originalSpellId = 33072; break; + case 48820: originalSpellId = 48824; break; + case 48821: originalSpellId = 48825; break; default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in JoW",triggeredByAura->GetSpellProto()->Id); - return false; + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in HShock",procSpell->Id); + return false; } - - pVictim->CastSpell(pVictim,triggered_spell_id,true,castItem,triggeredByAura,GetGUID()); - return true; // no hidden cooldown } - //Judgement of Light - case 299: + SpellEntry const *originalSpell = sSpellStore.LookupEntry(originalSpellId); + if(!originalSpell) { - if(!pVictim || !pVictim->isAlive()) - return false; - - // overwrite non existing triggered spell call in spell.dbc - switch(triggeredByAura->GetSpellProto()->Id) - { - case 20185: - triggered_spell_id = 20267; // Rank 1 - break; - case 20344: - triggered_spell_id = 20341; // Rank 2 - break; - case 20345: - triggered_spell_id = 20342; // Rank 3 - break; - case 20346: - triggered_spell_id = 20343; // Rank 4 - break; - case 27162: - triggered_spell_id = 27163; // Rank 5 - break; - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in JoL",triggeredByAura->GetSpellProto()->Id); - return false; - } - pVictim->CastSpell(pVictim,triggered_spell_id,true,castItem,triggeredByAura,GetGUID()); - return true; // no hidden cooldown + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu",originalSpellId); + return false; } + // percent stored in effect 1 (class scripts) base points + int32 cost = originalSpell->manaCost + originalSpell->ManaCostPercentage * GetCreateMana() / 100; + basepoints0 = cost*(auraSpellInfo->EffectBasePoints[1]+1)/100; + trigger_spell_id = 20272; + target = this; } - } - // custom check for proc spell - switch(auraSpellInfo->Id) - { - // Bonus Healing (item spell) - case 40971: + // Lightning Capacitor + else if (auraSpellInfo->Id==37657) { if(!pVictim || !pVictim->isAlive()) return false; + // stacking + CastSpell(this, 37658, true, NULL, triggeredByAura); - // bonus if health < 50% - if(pVictim->GetHealth() >= pVictim->GetMaxHealth()*triggeredByAura->GetModifier()->m_amount/100) + Aura * dummy = GetDummyAura(37658); + // release at 3 aura in stack (cont contain in basepoint of trigger aura) + if(!dummy || dummy->GetStackAmount() < triggerAmount) return false; - // cast at target positive spell + RemoveAurasDueToSpell(37658); + trigger_spell_id = 37661; target = pVictim; - break; } - } - switch(triggered_spell_id) - { - // Seal of Command - case 20424: - // prevent chain of triggered spell from same triggered spell - if(procSpell && procSpell->Id==20424) + // Thunder Capacitor + else if (auraSpellInfo->Id == 54841) + { + if(!pVictim || !pVictim->isAlive()) return false; - break; + // stacking + CastSpell(this, 54842, true, NULL, triggeredByAura); + + // counting + Aura * dummy = GetDummyAura(54842); + // release at 3 aura in stack (cont contain in basepoint of trigger aura) + if(!dummy || dummy->GetStackAmount() < triggerAmount) + return false; + + RemoveAurasDueToSpell(54842); + trigger_spell_id = 54843; + target = pVictim; + } + break; } - break; - } - case SPELLFAMILY_SHAMAN: - { - if(auraSpellInfo->SpellFamilyFlags == 0x0000000000000000) + case SPELLFAMILY_SHAMAN: { - switch(auraSpellInfo->SpellIconID) + // Lightning Shield (overwrite non existing triggered spell call in spell.dbc + if(auraSpellInfo->SpellFamilyFlags[0] & 0x400) { - case 19: - { - switch(auraSpellInfo->Id) - { - case 23551: // Lightning Shield - Tier2: 8 pieces proc shield - { - // Lightning Shield (overwrite non existing triggered spell call in spell.dbc) - triggered_spell_id = 23552; - target = pVictim; - break; - } - case 23552: // Lightning Shield - trigger shield damage - { - // Lightning Shield (overwrite non existing triggered spell call in spell.dbc) - triggered_spell_id = 27635; - target = pVictim; - break; - } - } - break; - } - // Mana Surge (Shaman T1 bonus) - case 87: + switch(auraSpellInfo->Id) { - if(!procSpell) - return false; - - basepoints0 = procSpell->manaCost * 35/100; - triggered_spell_id = 23571; - target = this; - break; + case 324: // Rank 1 + trigger_spell_id = 26364; break; + case 325: // Rank 2 + trigger_spell_id = 26365; break; + case 905: // Rank 3 + trigger_spell_id = 26366; break; + case 945: // Rank 4 + trigger_spell_id = 26367; break; + case 8134: // Rank 5 + trigger_spell_id = 26369; break; + case 10431: // Rank 6 + trigger_spell_id = 26370; break; + case 10432: // Rank 7 + trigger_spell_id = 26363; break; + case 25469: // Rank 8 + trigger_spell_id = 26371; break; + case 25472: // Rank 9 + trigger_spell_id = 26372; break; + case 49280: // Rank 10 + trigger_spell_id = 49278; break; + case 49281: // Rank 11 + trigger_spell_id = 49279; break; + default: + sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in LShield", auraSpellInfo->Id); + return false; } - //Nature's Guardian - case 2013: - { - if(GetTypeId()!=TYPEID_PLAYER) - return false; - - // damage taken that reduces below 30% health - // does NOT mean you must have been >= 30% before - if (10*(int32(GetHealth())-int32(damage)) >= 3*GetMaxHealth()) - return false; - - triggered_spell_id = 31616; + } + // Lightning Shield (The Ten Storms set) + else if (auraSpellInfo->Id == 23551) + { + trigger_spell_id = 23552; + target = pVictim; + } + // Damage from Lightning Shield (The Ten Storms set) + else if (auraSpellInfo->Id == 23552) + trigger_spell_id = 27635; + // Mana Surge (The Earthfury set) + else if (auraSpellInfo->Id == 23572) + { + if(!procSpell) + return false; + basepoints0 = procSpell->manaCost * 35 / 100; + trigger_spell_id = 23571; + target = this; + } + // Nature's Guardian + else if (auraSpellInfo->SpellIconID == 2013) + { + // Check health condition - should drop to less 30% (damage deal after this!) + if (!(10*(int32(GetHealth() - damage)) < 3 * GetMaxHealth())) + return false; - // need check cooldown now - if( cooldown && ((Player*)this)->HasSpellCooldown(triggered_spell_id)) - return false; + if(pVictim && pVictim->isAlive()) + pVictim->getThreatManager().modifyThreatPercent(this,-10); - basepoints0 = triggeredByAura->GetModifier()->m_amount * GetMaxHealth() / 100; - target = this; - if(pVictim && pVictim->isAlive()) - pVictim->getThreatManager().modifyThreatPercent(this,-10); - break; - } + basepoints0 = triggerAmount * GetMaxHealth() / 100; + trigger_spell_id = 31616; + target = this; } - } - - // Water Shield (we can't set cooldown for main spell - it's player casted spell - if((auraSpellInfo->SpellFamilyFlags & 0x0000002000000000LL) && auraSpellInfo->SpellVisual==7358) - { - target = this; break; } - - // Lightning Shield - if((auraSpellInfo->SpellFamilyFlags & 0x00000400) && auraSpellInfo->SpellVisual==37) - { - // overwrite non existing triggered spell call in spell.dbc - switch(triggeredByAura->GetSpellProto()->Id) - { - case 324: - triggered_spell_id = 26364; break; // Rank 1 - case 325: - triggered_spell_id = 26365; break; // Rank 2 - case 905: - triggered_spell_id = 26366; break; // Rank 3 - case 945: - triggered_spell_id = 26367; break; // Rank 4 - case 8134: - triggered_spell_id = 26369; break; // Rank 5 - case 10431: - triggered_spell_id = 26370; break; // Rank 6 - case 10432: - triggered_spell_id = 26363; break; // Rank 7 - case 25469: - triggered_spell_id = 26371; break; // Rank 8 - case 25472: - triggered_spell_id = 26372; break; // Rank 9 - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in LShield",triggeredByAura->GetSpellProto()->Id); + case SPELLFAMILY_DEATHKNIGHT: + { + // Acclimation + if (auraSpellInfo->SpellIconID == 1930) + { + if (!procSpell) return false; + switch(GetFirstSchoolInMask(GetSpellSchoolMask(procSpell))) + { + case SPELL_SCHOOL_NORMAL: + return false; // ignore + case SPELL_SCHOOL_HOLY: trigger_spell_id = 50490; break; + case SPELL_SCHOOL_FIRE: trigger_spell_id = 50362; break; + case SPELL_SCHOOL_NATURE: trigger_spell_id = 50488; break; + case SPELL_SCHOOL_FROST: trigger_spell_id = 50485; break; + case SPELL_SCHOOL_SHADOW: trigger_spell_id = 50489; break; + case SPELL_SCHOOL_ARCANE: trigger_spell_id = 54373; break; + default: + return false; + } + } + // Blood Presence + else if (auraSpellInfo->Id == 48266) + { + if (GetTypeId() != TYPEID_PLAYER) + return false; + if (!((Player*)this)->isHonorOrXPTarget(pVictim)) + return false; + trigger_spell_id = 50475; + basepoints0 = damage * triggerAmount / 100; } - - target = pVictim; break; } - break; - } - } - - // standard non-dummy case - if(!triggered_spell_id) - { - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u have 0 in EffectTriggered[%d], not handled custom case?",auraSpellInfo->Id,triggeredByAura->GetEffIndex()); - return false; - } - - SpellEntry const* triggerEntry = sSpellStore.LookupEntry(triggered_spell_id); - - if(!triggerEntry) - { - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u have not existed EffectTriggered[%d]=%u, not handled custom case?",auraSpellInfo->Id,triggeredByAura->GetEffIndex(),triggered_spell_id); - return false; - } - - // not allow proc extra attack spell at extra attack - if( m_extraAttacks && IsSpellHaveEffect(triggerEntry,SPELL_EFFECT_ADD_EXTRA_ATTACKS) ) - return false; - - if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(triggered_spell_id)) - return false; - - // default case - if(!target || target!=this && !target->isAlive()) - return false; - - if(basepoints0) - CastCustomSpell(target,triggered_spell_id,&basepoints0,NULL,NULL,true,castItem,triggeredByAura); - else - CastSpell(target,triggered_spell_id,true,castItem,triggeredByAura); - - if( cooldown && GetTypeId()==TYPEID_PLAYER ) - ((Player*)this)->AddSpellCooldown(triggered_spell_id,0,time(NULL) + cooldown); - - return true; -} -*/ - -bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlags, uint32 procEx, uint32 cooldown) -{ - // Get triggered aura spell info - SpellEntry const* auraSpellInfo = triggeredByAura->GetSpellProto(); - - // Basepoints of trigger aura - int32 triggerAmount = triggeredByAura->GetModifier()->m_amount; - - // Set trigger spell id, target, custom basepoints - uint32 trigger_spell_id = auraSpellInfo->EffectTriggerSpell[triggeredByAura->GetEffIndex()]; - Unit* target = NULL; - int32 basepoints0 = 0; - - Item* castItem = triggeredByAura->GetCastItemGUID() && GetTypeId()==TYPEID_PLAYER - ? ((Player*)this)->GetItemByGuid(triggeredByAura->GetCastItemGUID()) : NULL; - - // Try handle uncnown trigger spells - if (sSpellStore.LookupEntry(trigger_spell_id)==NULL) - switch (auraSpellInfo->SpellFamilyName) - { - //===================================================================== - // Generic class - // ==================================================================== - // ..... - //===================================================================== - case SPELLFAMILY_GENERIC: -// if (auraSpellInfo->Id==34082) // Advantaged State (DND) -// trigger_spell_id = ???; - if (auraSpellInfo->Id == 23780) // Aegis of Preservation (Aegis of Preservation trinket) - trigger_spell_id = 23781; -// else if (auraSpellInfo->Id==43504) // Alterac Valley OnKill Proc Aura -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==37030) // Chaotic Temperament -// trigger_spell_id = ; - else if (auraSpellInfo->Id==43820) // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket) - { - // Pct value stored in dummy - basepoints0 = pVictim->GetCreateHealth() * auraSpellInfo->EffectBasePoints[1] / 100; - target = pVictim; - break; - } -// else if (auraSpellInfo->Id==41248) // Consuming Strikes -// trigger_spell_id = 41249; -// else if (auraSpellInfo->Id==41054) // Copy Weapon -// trigger_spell_id = 41055; -// else if (auraSpellInfo->Id==31255) // Deadly Swiftness (Rank 1) -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==5301) // Defensive State (DND) -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==13358) // Defensive State (DND) -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==16092) // Defensive State (DND) -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==24949) // Defensive State 2 (DND) -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==40329) // Demo Shout Sensor -// trigger_spell_id = ; - // Desperate Defense (Stonescythe Whelp, Stonescythe Alpha, Stonescythe Ambusher) - else if (auraSpellInfo->Id == 33896) - trigger_spell_id = 33898; -// else if (auraSpellInfo->Id==18943) // Double Attack -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==19194) // Double Attack -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==19817) // Double Attack -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==19818) // Double Attack -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==22835) // Drunken Rage -// trigger_spell_id = 14822; - /* - else if (auraSpellInfo->SpellIconID==191) // Elemental Response - { - switch (auraSpellInfo->Id && auraSpellInfo->AttributesEx==0) - { - case 34191: - case 34329: - case 34524: - case 34582: - case 36733:break; - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Elemental Response",auraSpellInfo->Id); - return false; - } - //This generic aura self-triggers a different spell for each school of magic that lands on the wearer: - switch (procSpell->School) - { - case SPELL_SCHOOL_FIRE: trigger_spell_id = 34192;break;//Fire: 34192 - case SPELL_SCHOOL_FROST: trigger_spell_id = 34193;break;//Frost: 34193 - case SPELL_SCHOOL_ARCANE: trigger_spell_id = 34194;break;//Arcane: 34194 - case SPELL_SCHOOL_NATURE: trigger_spell_id = 34195;break;//Nature: 34195 - case SPELL_SCHOOL_SHADOW: trigger_spell_id = 34196;break;//Shadow: 34196 - case SPELL_SCHOOL_HOLY: trigger_spell_id = 34197;break;//Holy: 34197 - case SPELL_SCHOOL_NORMAL: trigger_spell_id = 34198;break;//Physical: 34198 - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u Elemental Response wrong school",auraSpellInfo->Id); - return false; - } - }*/ -// else if (auraSpellInfo->Id==6542) // Enraged Defense -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==40364) // Entangling Roots Sensor -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==33207) // Gossip NPC Periodic - Fidget -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==35321) // Gushing Wound -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==38363) // Gushing Wound -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==39215) // Gushing Wound -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==40250) // Improved Duration -// trigger_spell_id = ; - else if (auraSpellInfo->Id==27522) // Mana Drain Trigger - { - // On successful melee or ranged attack gain $29471s1 mana and if possible drain $27526s1 mana from the target. - if (this && this->isAlive()) - CastSpell(this, 29471, true, castItem, triggeredByAura); - if (pVictim && pVictim->isAlive()) - CastSpell(pVictim, 27526, true, castItem, triggeredByAura); - return true; - } - else if (auraSpellInfo->Id==24905) // Moonkin Form (Passive) - { - // Elune's Touch (instead non-existed triggered spell) 30% from AP - trigger_spell_id = 33926; - basepoints0 = GetTotalAttackPowerValue(BASE_ATTACK) * 30 / 100; - target = this; - } -// else if (auraSpellInfo->Id==43453) // Rune Ward -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==7137) // Shadow Charge (Rank 1) -// trigger_spell_id = ; - // Shaleskin (Shaleskin Flayer, Shaleskin Ripper) 30023 trigger -// else if (auraSpellInfo->Id==36576) -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==34783) // Spell Reflection -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==36096) // Spell Reflection -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==36207) // Steal Weapon -// trigger_spell_id = ; -// else if (auraSpellInfo->Id==35205) // Vanish - break; - //===================================================================== - // Mage - //===================================================================== - // Blazing Speed (Rank 1,2) trigger = 18350 - //===================================================================== - case SPELLFAMILY_MAGE: - // Blazing Speed - if (auraSpellInfo->SpellIconID == 2127) - { - switch (auraSpellInfo->Id) - { - case 31641: // Rank 1 - case 31642: // Rank 2 - trigger_spell_id = 31643; - break; - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Blazing Speed",auraSpellInfo->Id); - return false; - } - } - break; - //===================================================================== - // Warrior - //===================================================================== - // Rampage (Rank 1-3) trigger = 18350 - //===================================================================== - case SPELLFAMILY_WARRIOR: - // Rampage - if (auraSpellInfo->SpellIconID == 2006 && auraSpellInfo->SpellFamilyFlags==0x100000) - { - switch(auraSpellInfo->Id) - { - case 29801: trigger_spell_id = 30029; break; // Rank 1 - case 30030: trigger_spell_id = 30031; break; // Rank 2 - case 30033: trigger_spell_id = 30032; break; // Rank 3 - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in Rampage",auraSpellInfo->Id); - return false; - } - } - break; - //===================================================================== - // Warlock - //===================================================================== - // Pyroclasm trigger = 18350 - // Drain Soul (Rank 1-5) trigger = 0 - //===================================================================== - case SPELLFAMILY_WARLOCK: - { - // Pyroclasm - if (auraSpellInfo->SpellIconID == 1137) - { - if(!pVictim || !pVictim->isAlive() || pVictim == this || procSpell == NULL) - return false; - // Calculate spell tick count for spells - uint32 tick = 1; // Default tick = 1 - - // Hellfire have 15 tick - if (procSpell->SpellFamilyFlags&0x0000000000000040LL) - tick = 15; - // Rain of Fire have 4 tick - else if (procSpell->SpellFamilyFlags&0x0000000000000020LL) - tick = 4; - else - return false; - - // Calculate chance = baseChance / tick - float chance = 0; - switch (auraSpellInfo->Id) - { - case 18096: chance = 13.0f / tick; break; - case 18073: chance = 26.0f / tick; break; - } - // Roll chance - if (!roll_chance_f(chance)) - return false; - - trigger_spell_id = 18093; - } - // Drain Soul - else if (auraSpellInfo->SpellFamilyFlags & 0x0000000000004000LL) - { - Unit::AuraList const& mAddFlatModifier = GetAurasByType(SPELL_AURA_ADD_FLAT_MODIFIER); - for(Unit::AuraList::const_iterator i = mAddFlatModifier.begin(); i != mAddFlatModifier.end(); ++i) - { - if ((*i)->GetModifier()->m_miscvalue == SPELLMOD_CHANCE_OF_SUCCESS && (*i)->GetSpellProto()->SpellIconID == 113) - { - int32 value2 = CalculateSpellDamage((*i)->GetSpellProto(),2,(*i)->GetSpellProto()->EffectBasePoints[2],this); - basepoints0 = value2 * GetMaxPower(POWER_MANA) / 100; - } - } - if ( basepoints0 == 0 ) - return false; - trigger_spell_id = 18371; - } - break; - } - //===================================================================== - // Priest - //===================================================================== - // Greater Heal Refund trigger = 18350 - // Blessed Recovery (Rank 1-3) trigger = 18350 - // Shadowguard (1-7) trigger = 28376 - //===================================================================== - case SPELLFAMILY_PRIEST: - { - // Greater Heal Refund - if (auraSpellInfo->Id==37594) - trigger_spell_id = 37595; - // Shadowguard - else if(auraSpellInfo->SpellFamilyFlags==0x100080000000LL && auraSpellInfo->SpellVisual==7958) - { - switch(auraSpellInfo->Id) - { - case 18137: trigger_spell_id = 28377; break; // Rank 1 - case 19308: trigger_spell_id = 28378; break; // Rank 2 - case 19309: trigger_spell_id = 28379; break; // Rank 3 - case 19310: trigger_spell_id = 28380; break; // Rank 4 - case 19311: trigger_spell_id = 28381; break; // Rank 5 - case 19312: trigger_spell_id = 28382; break; // Rank 6 - case 25477: trigger_spell_id = 28385; break; // Rank 7 - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in SG", auraSpellInfo->Id); - return false; - } - } - // Blessed Recovery - else if (auraSpellInfo->SpellIconID == 1875) - { - switch (auraSpellInfo->Id) - { - case 27811: trigger_spell_id = 27813; break; - case 27815: trigger_spell_id = 27817; break; - case 27816: trigger_spell_id = 27818; break; - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id); - return false; - } - basepoints0 = damage * triggerAmount / 100 / 3; - target = this; - } - break; - } - //===================================================================== - // Druid - // ==================================================================== - // Druid Forms Trinket trigger = 18350 - // Entangling Roots trigger = 30023 - // Leader of the Pack trigger = 18350 - //===================================================================== - case SPELLFAMILY_DRUID: - { - // Druid Forms Trinket - if (auraSpellInfo->Id==37336) - { - switch(m_form) - { - case 0: trigger_spell_id = 37344;break; - case FORM_CAT: trigger_spell_id = 37341;break; - case FORM_BEAR: - case FORM_DIREBEAR: trigger_spell_id = 37340;break; - case FORM_TREE: trigger_spell_id = 37342;break; - case FORM_MOONKIN: trigger_spell_id = 37343;break; - default: - return false; - } - } -// else if (auraSpellInfo->Id==40363)// Entangling Roots () -// trigger_spell_id = ????; - // Leader of the Pack - else if (auraSpellInfo->Id == 24932) - { - if (triggerAmount == 0) - return false; - basepoints0 = triggerAmount * GetMaxHealth() / 100; - trigger_spell_id = 34299; - } - break; - } - //===================================================================== - // Hunter - // ==================================================================== - // ...... - //===================================================================== - case SPELLFAMILY_HUNTER: - break; - //===================================================================== - // Paladin - // ==================================================================== - // Blessed Life trigger = 31934 - // Healing Discount trigger = 18350 - // Illumination (Rank 1-5) trigger = 18350 - // Judgement of Light (Rank 1-5) trigger = 5373 - // Judgement of Wisdom (Rank 1-4) trigger = 1826 - // Lightning Capacitor trigger = 18350 - //===================================================================== - case SPELLFAMILY_PALADIN: - { - /* // Blessed Life - if (auraSpellInfo->SpellIconID == 2137) - { - switch (auraSpellInfo->Id) - { - case 31828: // Rank 1 - case 31829: // Rank 2 - case 31830: // Rank 3 + default: break; - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Blessed Life", auraSpellInfo->Id); - return false; - } - }*/ - // Healing Discount - if (auraSpellInfo->Id==37705) - { - trigger_spell_id = 37706; - target = this; - } - // Judgement of Light and Judgement of Wisdom - else if (auraSpellInfo->SpellFamilyFlags & 0x0000000000080000LL) - { - switch (auraSpellInfo->Id) - { - // Judgement of Light - case 20185: trigger_spell_id = 20267;break; // Rank 1 - case 20344: trigger_spell_id = 20341;break; // Rank 2 - case 20345: trigger_spell_id = 20342;break; // Rank 3 - case 20346: trigger_spell_id = 20343;break; // Rank 4 - case 27162: trigger_spell_id = 27163;break; // Rank 5 - // Judgement of Wisdom - case 20186: trigger_spell_id = 20268;break; // Rank 1 - case 20354: trigger_spell_id = 20352;break; // Rank 2 - case 20355: trigger_spell_id = 20353;break; // Rank 3 - case 27164: trigger_spell_id = 27165;break; // Rank 4 - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u miss posibly Judgement of Light/Wisdom", auraSpellInfo->Id); - return false; - } - pVictim->CastSpell(pVictim, trigger_spell_id, true, castItem, triggeredByAura); - return true; // no hidden cooldown - } - // Illumination - else if (auraSpellInfo->SpellIconID==241) - { - if(!procSpell) - return false; - // procspell is triggered spell but we need mana cost of original casted spell - uint32 originalSpellId = procSpell->Id; - // Holy Shock - if(procSpell->SpellFamilyFlags & 0x00200000) - { - switch(procSpell->Id) - { - case 25914: originalSpellId = 20473; break; - case 25913: originalSpellId = 20929; break; - case 25903: originalSpellId = 20930; break; - case 27175: originalSpellId = 27174; break; - case 33074: originalSpellId = 33072; break; - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in HShock",procSpell->Id); - return false; - } - } - SpellEntry const *originalSpell = sSpellStore.LookupEntry(originalSpellId); - if(!originalSpell) - { - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu",originalSpellId); - return false; - } - // percent stored in effect 1 (class scripts) base points - basepoints0 = originalSpell->manaCost*(auraSpellInfo->EffectBasePoints[1]+1)/100; - trigger_spell_id = 20272; - target = this; - } - // Lightning Capacitor - else if (auraSpellInfo->Id==37657) - { - if(!pVictim || !pVictim->isAlive()) - return false; - // stacking - CastSpell(this, 37658, true, NULL, triggeredByAura); - // counting - Aura * dummy = GetDummyAura(37658); - if (!dummy) - return false; - // release at 3 aura in stack (cont contain in basepoint of trigger aura) - if(dummy->GetStackAmount() <= 2) - return false; - - RemoveAurasDueToSpell(37658); - trigger_spell_id = 37661; - target = pVictim; - } - break; - } - //===================================================================== - // Shaman - //==================================================================== - // Lightning Shield trigger = 18350 - // Mana Surge trigger = 18350 - // Nature's Guardian (Rank 1-5) trigger = 18350 - //===================================================================== - case SPELLFAMILY_SHAMAN: - { - //Lightning Shield (overwrite non existing triggered spell call in spell.dbc - if(auraSpellInfo->SpellFamilyFlags==0x00000400 && auraSpellInfo->SpellVisual==37) - { - switch(auraSpellInfo->Id) - { - case 324: trigger_spell_id = 26364; break; // Rank 1 - case 325: trigger_spell_id = 26365; break; // Rank 2 - case 905: trigger_spell_id = 26366; break; // Rank 3 - case 945: trigger_spell_id = 26367; break; // Rank 4 - case 8134: trigger_spell_id = 26369; break; // Rank 5 - case 10431: trigger_spell_id = 26370; break; // Rank 6 - case 10432: trigger_spell_id = 26363; break; // Rank 7 - case 25469: trigger_spell_id = 26371; break; // Rank 8 - case 25472: trigger_spell_id = 26372; break; // Rank 9 - default: - sLog.outError("Unit::HandleProcTriggerSpell: Spell %u not handled in LShield", auraSpellInfo->Id); - return false; - } - } - // Lightning Shield (The Ten Storms set) - else if (auraSpellInfo->Id == 23551) - { - trigger_spell_id = 23552; - target = pVictim; - } - // Damage from Lightning Shield (The Ten Storms set) - else if (auraSpellInfo->Id == 23552) - trigger_spell_id = 27635; - // Mana Surge (The Earthfury set) - else if (auraSpellInfo->Id == 23572) - { - if(!procSpell) - return false; - basepoints0 = procSpell->manaCost * 35 / 100; - trigger_spell_id = 23571; - target = this; - } - else if (auraSpellInfo->SpellIconID == 2013) //Nature's Guardian - { - // Check health condition - should drop to less 30% (damage deal after this!) - if (!(10*(int32(GetHealth() - damage)) < 3 * GetMaxHealth())) - return false; - - if(pVictim && pVictim->isAlive()) - pVictim->getThreatManager().modifyThreatPercent(this,-10); - - basepoints0 = triggerAmount * GetMaxHealth() / 100; - trigger_spell_id = 31616; - target = this; - } - break; - } - // default - default: - break; + } } // All ok. Check current trigger spell @@ -7695,6 +6828,15 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB return false; break; } + // Rapid Recuperation + case 53228: + case 53232: + { + // This effect only from Rapid Fire (ability cast) + if (!(procSpell->SpellFamilyFlags[0] & 0x20)) + return false; + break; + } } // Costum basepoints/target for exist spell @@ -7724,11 +6866,16 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB // Need add combopoint AFTER finish movie (or they dropped in finish phase) break; } + // Bloodthirst (($m/100)% of max health) + case 23880: + { + basepoints0 = int32(GetMaxHealth() * triggerAmount / 10000); + break; + } // Shamanistic Rage triggered spell case 30824: { basepoints0 = int32(GetTotalAttackPowerValue(BASE_ATTACK) * triggerAmount / 100); - trigger_spell_id = 30824; break; } // Enlightenment (trigger only from mana cost spells) @@ -7738,6 +6885,59 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB return false; break; } + // Brain Freeze + case 57761: + { + if(!procSpell) + return false; + // For trigger from Blizzard need exist Improved Blizzard + if (procSpell->SpellFamilyName==SPELLFAMILY_MAGE && procSpell->SpellFamilyFlags[0] & 0x80) + { + bool found = false; + AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) + { + int32 script = (*i)->GetModifier()->m_miscvalue; + if(script==836 || script==988 || script==989) + { + found=true; + break; + } + } + if(!found) + return false; + } + break; + } + // Astral Shift + case 52179: + { + if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == pVictim) + return false; + + // Need stun, fear or silence mechanic + if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_SILENCE)|(1<<MECHANIC_STUN)|(1<<MECHANIC_FEAR)))) + return false; + break; + } + // Burning Determination + case 54748: + { + if(!procSpell) + return false; + // Need Interrupt or Silenced mechanic + if (!(GetAllSpellMechanicMask(procSpell) & ((1<<MECHANIC_INTERRUPT)|(1<<MECHANIC_SILENCE)))) + return false; + break; + } + // Lock and Load + case 56453: + { + // Proc only from trap activation (from periodic proc another aura of this spell) + if (!(procFlags & PROC_FLAG_ON_TRAP_ACTIVATION) || !roll_chance_i(triggerAmount)) + return false; + break; + } } if( cooldown && GetTypeId()==TYPEID_PLAYER && ((Player*)this)->HasSpellCooldown(trigger_spell_id)) @@ -7764,7 +6964,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB return true; } -bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown) +bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura *triggeredByAura, SpellEntry const *procSpell, uint32 cooldown) { int32 scriptId = triggeredByAura->GetModifier()->m_miscvalue; @@ -7780,21 +6980,21 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAur { case 836: // Improved Blizzard (Rank 1) { - if (!procSpell || procSpell->SpellVisual!=9487) + if (!procSpell || procSpell->SpellVisual[0]!=9487) return false; triggered_spell_id = 12484; break; } case 988: // Improved Blizzard (Rank 2) { - if (!procSpell || procSpell->SpellVisual!=9487) + if (!procSpell || procSpell->SpellVisual[0]!=9487) return false; triggered_spell_id = 12485; break; } case 989: // Improved Blizzard (Rank 3) { - if (!procSpell || procSpell->SpellVisual!=9487) + if (!procSpell || procSpell->SpellVisual[0]!=9487) return false; triggered_spell_id = 12486; break; @@ -7831,6 +7031,16 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura *triggeredByAur case 5497: // Improved Mana Gems (Serpent-Coil Braid) triggered_spell_id = 37445; // Mana Surge break; + case 8152: // Serendipity + { + // if heal your target over maximum health + if (pVictim->GetHealth() + damage < pVictim->GetMaxHealth()) + return false; + int32 cost = procSpell->manaCost + procSpell->ManaCostPercentage * GetCreateMana() / 100; + int32 basepoints0 = cost * triggeredByAura->GetModifier()->m_amount/100; + CastCustomSpell(this, 47762, &basepoints0, 0, 0, true, 0, triggeredByAura); + return true; + } } // not processed @@ -7972,11 +7182,11 @@ bool Unit::IsHostileTo(Unit const* unit) const return false; // Sanctuary - if(pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY) && pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY)) + if(pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY)) return false; // PvP FFA state - if(pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP) && pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP)) + if(pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) && pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) return true; //= PvP states @@ -8081,11 +7291,11 @@ bool Unit::IsFriendlyTo(Unit const* unit) const return true; // Sanctuary - if(pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY) && pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_SANCTUARY)) + if(pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY) && pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY)) return true; // PvP FFA state - if(pTester->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP) && pTarget->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP)) + if(pTester->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP) && pTarget->HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP)) return false; //= PvP states @@ -8214,6 +7424,11 @@ bool Unit::Attack(Unit *victim, bool meleeAttack) if(meleeAttack) addUnitState(UNIT_STAT_MELEE_ATTACKING); + + // set position before any AI calls/assistance + //if(GetTypeId()==TYPEID_UNIT) + // ((Creature*)this)->SetCombatStartPosition(GetPositionX(), GetPositionY(), GetPositionZ()); + m_attacking = victim; m_attacking->_addAttacker(this); @@ -8222,18 +7437,18 @@ bool Unit::Attack(Unit *victim, bool meleeAttack) if(GetTypeId()==TYPEID_UNIT) { + // should not let player enter combat by right clicking target + SetInCombatWith(victim); + if(victim->GetTypeId() == TYPEID_PLAYER) + victim->SetInCombatWith(this); + AddThreat(victim, 0.0f); + WorldPacket data(SMSG_AI_REACTION, 12); data << uint64(GetGUID()); data << uint32(AI_REACTION_AGGRO); // Aggro sound ((WorldObject*)this)->SendMessageToSet(&data, true); ((Creature*)this)->CallAssistance(); - - // should not let player enter combat by right clicking target - SetInCombatWith(victim); - if(victim->GetTypeId() == TYPEID_PLAYER) - victim->SetInCombatWith(this); - AddThreat(victim, 0.0f); } // delay offhand weapon attack to next attack time @@ -8343,51 +7558,7 @@ void Unit::RemoveAllAttackers() void Unit::ModifyAuraState(AuraState flag, bool apply) { - if (apply) - { - if (!HasFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1))) - { - SetFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); - if(GetTypeId() == TYPEID_PLAYER) - { - const PlayerSpellMap& sp_list = ((Player*)this)->GetSpellMap(); - for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr) - { - if(itr->second->state == PLAYERSPELL_REMOVED) continue; - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); - if (!spellInfo || !IsPassiveSpell(itr->first)) continue; - if (spellInfo->CasterAuraState == flag) - CastSpell(this, itr->first, true, NULL); - } - } - } - } - else - { - if (HasFlag(UNIT_FIELD_AURASTATE,1<<(flag-1))) - { - RemoveFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1)); - Unit::AuraMap& tAuras = GetAuras(); - for (Unit::AuraMap::iterator itr = tAuras.begin(); itr != tAuras.end();) - { - SpellEntry const* spellProto = (*itr).second->GetSpellProto(); - if (spellProto->CasterAuraState == flag) - { - // exceptions (applied at state but not removed at state change) - // Rampage - if(spellProto->SpellIconID==2006 && spellProto->SpellFamilyName==SPELLFAMILY_WARRIOR && spellProto->SpellFamilyFlags==0x100000) - { - ++itr; - continue; - } - - RemoveAura(itr); - } - else - ++itr; - } - } - } + ApplyModFlag(UNIT_FIELD_AURASTATE, 1<<(flag-1), apply); } Unit *Unit::GetOwner() const @@ -8437,6 +7608,7 @@ Unit* Unit::GetCharm() const sLog.outError("Unit::GetCharm: Charmed creature %u not exist.",GUID_LOPART(charm_guid)); const_cast<Unit*>(this)->SetCharm(0); + //const_cast<Unit*>(this)->SetMover(0); } return NULL; @@ -8519,6 +7691,7 @@ void Unit::SendHealSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, bool c data.append(GetPackGUID()); data << uint32(SpellID); data << uint32(Damage); + data << uint32(0); // over healing? data << uint8(critical ? 1 : 0); data << uint8(0); // unused in client? SendMessageToSet(&data, true); @@ -8535,76 +7708,29 @@ void Unit::SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, Po SendMessageToSet(&data, true); } -uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype) +uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack) { if(!spellProto || !pVictim || damagetype==DIRECT_DAMAGE ) return pdamage; - //if(spellProto->SchoolMask == SPELL_SCHOOL_MASK_NORMAL) - // return pdamage; - //damage = CalcArmorReducedDamage(pVictim, damage); - - int32 BonusDamage = 0; - if( GetTypeId()==TYPEID_UNIT ) - { - // Pets just add their bonus damage to their spell damage - // note that their spell damage is just gain of their own auras - if (((Creature*)this)->isPet()) - { - BonusDamage = ((Pet*)this)->GetBonusDamage(); - } - // For totems get damage bonus from owner (statue isn't totem in fact) - else if (((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE) - { - if(Unit* owner = GetOwner()) - return owner->SpellDamageBonus(pVictim, spellProto, pdamage, damagetype); - } - } - - // Damage Done - uint32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); - - // Taken/Done fixed damage bonus auras - int32 DoneAdvertisedBenefit = SpellBaseDamageBonus(GetSpellSchoolMask(spellProto))+BonusDamage; - int32 TakenAdvertisedBenefit = SpellBaseDamageBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); - - // Damage over Time spells bonus calculation - float DotFactor = 1.0f; - if(damagetype == DOT) + // For totems get damage bonus from owner (statue isn't totem in fact) + if( GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE) { - int32 DotDuration = GetSpellDuration(spellProto); - // 200% limit - if(DotDuration > 0) - { - if(DotDuration > 30000) DotDuration = 30000; - if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; - int x = 0; - for(int j = 0; j < 3; j++) - { - if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE || - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) - { - x = j; - break; - } - } - int DotTicks = 6; - if(spellProto->EffectAmplitude[x] != 0) - DotTicks = DotDuration / spellProto->EffectAmplitude[x]; - if(DotTicks) - { - DoneAdvertisedBenefit /= DotTicks; - TakenAdvertisedBenefit /= DotTicks; - } - } + if(Unit* owner = GetOwner()) + return owner->SpellDamageBonus(pVictim, spellProto, pdamage, damagetype); } // Taken/Done total percent damage auras float DoneTotalMod = 1.0f; float TakenTotalMod = 1.0f; + int32 DoneTotal = 0; + int32 TakenTotal = 0; // ..done + // Pet damage + if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() ) + DoneTotalMod *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank); + AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) { @@ -8614,84 +7740,133 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 (*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 ) // 0 == any inventory type (not wand then) { - DoneTotalMod *= ((*i)->GetModifierValue() +100.0f)/100.0f; + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; } } uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); + // Add flat bonus from spell damage versus + DoneTotal += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS, creatureTypeMask); AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i) if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) - DoneTotalMod *= ((*i)->GetModifierValue() +100.0f)/100.0f; - - // ..taken - AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); - for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i) - if( (*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto) ) - TakenTotalMod *= ((*i)->GetModifierValue() +100.0f)/100.0f; + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; - // .. taken pct: scripted (increases damage of * against targets *) - AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + // done scripted mod (take it from owner) + Unit *owner = GetOwner(); + if (!owner) owner = this; + AuraList const& mOverrideClassScript= owner->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) { + if (!(*i)->isAffectedOnSpell(spellProto)) + continue; switch((*i)->GetModifier()->m_miscvalue) { - //Molten Fury - case 4920: case 4919: - if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT)) - TakenTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f; break; - } - } - - // .. taken pct: dummy auras - AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); - for(AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i) - { - switch((*i)->GetSpellProto()->SpellIconID) - { - //Cheat Death - case 2109: - if( ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) ) - { - if(pVictim->GetTypeId() != TYPEID_PLAYER) - continue; - float mod = -((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2*4; - if (mod < (*i)->GetModifier()->m_amount) - mod = (*i)->GetModifier()->m_amount; - TakenTotalMod *= (mod+100.0f)/100.0f; - } + case 4920: // Molten Fury + case 4919: + case 6917: // Death's Embrace + case 6926: + case 6928: + { + if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT)) + DoneTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f; break; - //This is changed in WLK, using aura 255 - //Mangle - case 2312: - case 44955: - for(int j=0;j<3;j++) - { - if(GetEffectMechanic(spellProto, j)==MECHANIC_BLEED) + } + // Soul Siphon + case 4992: + case 4993: + { + // effect 1 m_amount + int32 maxPercent = (*i)->GetModifier()->m_amount; + // effect 0 m_amount + int32 stepPercent = CalculateSpellDamage((*i)->GetSpellProto(), 0, (*i)->GetSpellProto()->EffectBasePoints[0], this); + // count affliction effects and calc additional damage in percentage + int32 modPercent = 0; + AuraMap const& victimAuras = pVictim->GetAuras(); + for (AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) + { + SpellEntry const* m_spell = itr->second->GetSpellProto(); + if (m_spell->SpellFamilyName != SPELLFAMILY_WARLOCK || !(m_spell->SpellFamilyFlags[1] & 0x0004071B || m_spell->SpellFamilyFlags[0] & 0x8044C402)) + continue; + modPercent += stepPercent * itr->second->GetStackAmount(); + if (modPercent >= maxPercent) { - TakenTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f; + modPercent = maxPercent; break; } } + DoneTotalMod *= (modPercent+100.0f)/100.0f; break; + } + case 6916: // Death's Embrace + case 6925: + case 6927: + if (HasAuraState(AURA_STATE_HEALTHLESS_20_PERCENT)) + DoneTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f; + break; + case 5481: // Starfire Bonus + { + if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DRUID, 0x200002)) + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + break; + } + case 4418: // Increased Shock Damage + case 4554: // Increased Lightning Damage + case 4555: // Improved Moonfire + case 5142: // Increased Lightning Damage + case 5147: // Improved Consecration / Libram of Resurgence + case 5148: // Idol of the Shooting Star + case 6008: // Increased Lightning Damage / Totem of Hex + { + DoneTotal+=(*i)->GetModifier()->m_amount; + break; + } + // Tundra Stalker + // Merciless Combat + case 7277: + { + // Merciless Combat + if ((*i)->GetSpellProto()->SpellIconID == 2656) + { + if(pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT)) + DoneTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f; + } + else // Tundra Stalker + { + if (pVictim->GetAura(SPELL_AURA_DUMMY, SPELLFAMILY_DEATHKNIGHT,0, 0x04000000,0)) + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + break; + } + break; + } + case 7293: // Rage of Rivendare + { + if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_DEATHKNIGHT, 0,0x02000000,0)) + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + break; + } + // Twisted Faith + case 7377: + { + if (pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_PRIEST, 0x8000, 0,0, GetGUID())) + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + break; + } + // Marked for Death + case 7598: + case 7599: + case 7600: + case 7601: + case 7602: + { + if (pVictim->GetAura(SPELL_AURA_MOD_STALKED, SPELLFAMILY_HUNTER, 0x400)) + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + break; + } } } - // Distribute Damage over multiple effects, reduce by AoE - CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - - // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing - for(int j = 0; j < 3; ++j) - { - if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || - spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) - { - CastingTime /= 2; - break; - } - } - - switch(spellProto->SpellFamilyName) + /*switch(spellProto->SpellFamilyName) { case SPELLFAMILY_GENERIC: // Siphon Essence - 0% @@ -8705,7 +7880,7 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 CastingTime = 0; } // Darkmoon Card: Vengeance - 0.1% - else if (spellProto->SpellVisual == 9850 && spellProto->SpellIconID == 2230) + else if (spellProto->SpellVisual[0] == 9850 && spellProto->SpellIconID == 2230) { CastingTime = 3.5; } @@ -8808,21 +7983,10 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 DotFactor = 0.95f; CastingTime = 3500; } - // Seal of Righteousness - 10.2%/9.8% ( based on weapon type ) of Holy Damage, multiplied by weapon speed - else if((spellProto->SpellFamilyFlags & 0x8000000LL) && spellProto->SpellIconID == 25) + // Judgement of Righteousness - 32% + else if (spellProto->SpellFamilyFlags & 0x0000000000000400LL) { - Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); - float wspeed = GetAttackTime(BASE_ATTACK)/1000.0f; - - if( item && item->GetProto()->InventoryType == INVTYPE_2HWEAPON) - CastingTime = uint32(wspeed*3500*0.102f); - else - CastingTime = uint32(wspeed*3500*0.098f); - } - // Judgement of Righteousness - 73% - else if ((spellProto->SpellFamilyFlags & 1024) && spellProto->SpellIconID == 25) - { - CastingTime = 2555; + CastingTime = 1120; } // Seal of Vengeance - 17% per Fully Stacked Tick - 5 Applications else if ((spellProto->SpellFamilyFlags & 0x80000000000LL) && spellProto->SpellIconID == 2292) @@ -8840,11 +8004,6 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 { CastingTime = 0; } - // Seal of Righteousness trigger - already computed for parent spell - else if ( spellProto->SpellFamilyName==SPELLFAMILY_PALADIN && spellProto->SpellIconID==25 && spellProto->AttributesEx4 & 0x00800000LL ) - { - return pdamage; - } break; case SPELLFAMILY_SHAMAN: // totem attack @@ -8898,58 +8057,148 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 { CastingTime = 500; } - break; - case SPELLFAMILY_DRUID: - // Hurricane triggered spell - if((spellProto->SpellFamilyFlags & 0x400000LL) && spellProto->SpellIconID == 220) - { - CastingTime = 500; - } - break; - case SPELLFAMILY_WARRIOR: - case SPELLFAMILY_HUNTER: - case SPELLFAMILY_ROGUE: - CastingTime = 0; - break; - default: - break; - } + break;*/ - float LvlPenalty = CalculateLevelPenalty(spellProto); + // Custom scripted damage + // Ice Lance + if (spellProto->SpellFamilyName == SPELLFAMILY_MAGE && spellProto->SpellIconID == 186) + { + if (pVictim->isFrozen()) + DoneTotalMod *= 3.0f; + } - // Spellmod SpellDamage - //float SpellModSpellDamage = 100.0f; - float CoefficientPtc = DotFactor * 100.0f; - if(spellProto->SchoolMask != SPELL_SCHOOL_MASK_NORMAL) - CoefficientPtc *= ((float)CastingTime/3500.0f); + // ..taken + AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); + for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i) + if( (*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto) ) + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; - if(Player* modOwner = GetSpellModOwner()) - //modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,SpellModSpellDamage); - modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,CoefficientPtc); + // .. taken pct: dummy auras + if (pVictim->GetTypeId() == TYPEID_PLAYER) + { + //Cheat Death + if (Aura *dummy = pVictim->GetDummyAura(45182)) + { + float mod = -((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL)*2*4; + if (mod < dummy->GetModifier()->m_amount) + mod = dummy->GetModifier()->m_amount; + TakenTotalMod *= (mod+100.0f)/100.0f; + } + } - //SpellModSpellDamage /= 100.0f; - CoefficientPtc /= 100.0f; + // From caster spells + AuraList const& mOwnerTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER); + for(AuraList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i) + if( (*i)->GetCasterGUID() == GetGUID() && (*i)->isAffectedOnSpell(spellProto)) + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; - //float DoneActualBenefit = DoneAdvertisedBenefit * (CastingTime / 3500.0f) * DotFactor * SpellModSpellDamage * LvlPenalty; + // Mod damage from spell mechanic + uint32 mechanicMask = GetAllSpellMechanicMask(spellProto); + 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; + } - float DoneActualBenefit = DoneAdvertisedBenefit * CoefficientPtc * LvlPenalty; - float TakenActualBenefit = TakenAdvertisedBenefit * DotFactor * LvlPenalty; - if(spellProto->SpellFamilyName && spellProto->SchoolMask != SPELL_SCHOOL_MASK_NORMAL) - TakenActualBenefit *= ((float)CastingTime / 3500.0f); + // Taken/Done fixed damage bonus auras + int32 DoneAdvertisedBenefit = SpellBaseDamageBonus(GetSpellSchoolMask(spellProto)); + int32 TakenAdvertisedBenefit = SpellBaseDamageBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); + // Pets just add their bonus damage to their spell damage + // note that their spell damage is just gain of their own auras + if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) + DoneAdvertisedBenefit += ((Pet*)this)->GetBonusDamage(); + + // Check for table values + float coeff; + SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id); + if (bonus) + { + if (damagetype == DOT) + coeff = bonus->dot_damage; + else + coeff = bonus->direct_damage; + if (bonus->ap_bonus) + DoneTotal+=bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack; + } + // Default calculation + else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit) + { + // Damage Done from spell damage bonus + int32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); + if (IsChanneledSpell(spellProto)) + ModSpellCastTime(spellProto, CastingTime); + // Damage over Time spells bonus calculation + float DotFactor = 1.0f; + if(damagetype == DOT) + { + int32 DotDuration = GetSpellDuration(spellProto); + //apply casting time mods for channeled spells + if (IsChanneledSpell(spellProto)) + ModSpellCastTime(spellProto, DotDuration); + // 200% limit + if(DotDuration > 0) + { + if(DotDuration > 30000) DotDuration = 30000; + if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; + int x = 0; + for(int j = 0; j < 3; j++) + { + if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE || + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) + { + x = j; + break; + } + } + int32 DotTicks = 6; + if(spellProto->EffectAmplitude[x] != 0) + DotTicks = DotDuration / spellProto->EffectAmplitude[x]; + if(DotTicks) + { + DoneAdvertisedBenefit /= DotTicks; + TakenAdvertisedBenefit /= DotTicks; + } + } + } + // Distribute Damage over multiple effects, reduce by AoE + CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - float tmpDamage = (float(pdamage)+DoneActualBenefit)*DoneTotalMod; + // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing + for(int j = 0; j < 3; ++j) + { + if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || + spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) + { + CastingTime /= 2; + break; + } + } + if(spellProto->SchoolMask != SPELL_SCHOOL_MASK_NORMAL) + coeff = (CastingTime / 3500.0f) * DotFactor; + else + coeff = DotFactor; + } - // Add flat bonus from spell damage versus - tmpDamage += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS, creatureTypeMask); + float coeff2 = CalculateLevelPenalty(spellProto) * stack; + if(spellProto->SpellFamilyName) //TODO: fix this + TakenTotal+= TakenAdvertisedBenefit * coeff * coeff2; + if(Player* modOwner = GetSpellModOwner()) + { + coeff *= 100.0f; + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_SPELL_BONUS_DAMAGE, coeff); + coeff /= 100.0f; + } + DoneTotal += DoneAdvertisedBenefit * coeff * coeff2; - // apply spellmod to Done damage + float tmpDamage = (pdamage + DoneTotal) * DoneTotalMod; + // apply spellmod to Done damage (flat and pct) if(Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage); - tmpDamage = (tmpDamage+TakenActualBenefit)*TakenTotalMod; - - if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() ) - tmpDamage *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank); + tmpDamage = (tmpDamage + TakenTotal) * TakenTotalMod; return tmpDamage > 0 ? uint32(tmpDamage) : 0; } @@ -8966,32 +8215,29 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask) // -1 == any item class (not wand then) (*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 ) // 0 == any inventory type (not wand then) - DoneAdvertisedBenefit += (*i)->GetModifierValue(); + DoneAdvertisedBenefit += (*i)->GetModifier()->m_amount; if (GetTypeId() == TYPEID_PLAYER) { + // Base value + DoneAdvertisedBenefit +=((Player*)this)->GetBaseSpellDamageBonus(); + // Damage bonus from stats AuraList const& mDamageDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT); for(AuraList::const_iterator i = mDamageDoneOfStatPercent.begin();i != mDamageDoneOfStatPercent.end(); ++i) { if((*i)->GetModifier()->m_miscvalue & schoolMask) { - SpellEntry const* iSpellProto = (*i)->GetSpellProto(); - uint8 eff = (*i)->GetEffIndex(); - - // stat used dependent from next effect aura SPELL_AURA_MOD_SPELL_HEALING presence and misc value (stat index) - Stats usedStat = STAT_INTELLECT; - if(eff < 2 && iSpellProto->EffectApplyAuraName[eff+1]==SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT) - usedStat = Stats(iSpellProto->EffectMiscValue[eff+1]); - - DoneAdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifierValue() / 100.0f); + // stat used stored in miscValueB for this aura + Stats usedStat = Stats((*i)->GetMiscBValue()); + DoneAdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifier()->m_amount / 100.0f); } } // ... and attack power AuraList const& mDamageDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER); for(AuraList::const_iterator i =mDamageDonebyAP.begin();i != mDamageDonebyAP.end(); ++i) if ((*i)->GetModifier()->m_miscvalue & schoolMask) - DoneAdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifierValue() / 100.0f); + DoneAdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifier()->m_amount / 100.0f); } return DoneAdvertisedBenefit; @@ -9006,13 +8252,13 @@ int32 Unit::SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVic AuraList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE); for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i) if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) - TakenAdvertisedBenefit += (*i)->GetModifierValue(); + TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount; // ..taken AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN); for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i) if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0) - TakenAdvertisedBenefit += (*i)->GetModifierValue(); + TakenAdvertisedBenefit += (*i)->GetModifier()->m_amount; return TakenAdvertisedBenefit; } @@ -9041,30 +8287,77 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask); } // taken - if (pVictim && !IsPositiveSpell(spellProto->Id)) - { - // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE - crit_chance += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE, schoolMask); - // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE - crit_chance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE); - // Modify by player victim resilience - if (pVictim->GetTypeId() == TYPEID_PLAYER) - crit_chance -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL); + if (pVictim) + { + if (!IsPositiveSpell(spellProto->Id)) + { + // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE + crit_chance += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE, schoolMask); + // Modify critical chance by victim SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE + crit_chance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE); + // Modify by player victim resilience + if (pVictim->GetTypeId() == TYPEID_PLAYER) + crit_chance -= ((Player*)pVictim)->GetRatingBonusValue(CR_CRIT_TAKEN_SPELL); + } + // scripted (increase crit chance ... against ... target by x% - if(pVictim->isFrozen()) // Shatter + AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) { - AuraList const& mOverrideClassScript = GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); - for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) + if (!((*i)->isAffectedOnSpell(spellProto))) + continue; + switch((*i)->GetModifier()->m_miscvalue) { - switch((*i)->GetModifier()->m_miscvalue) + case 849: if (pVictim->isFrozen()) crit_chance+= 17.0f; break; //Shatter Rank 1 + case 910: if (pVictim->isFrozen()) crit_chance+= 34.0f; break; //Shatter Rank 2 + case 911: if (pVictim->isFrozen()) crit_chance+= 50.0f; break; //Shatter Rank 3 + case 7917: // Glyph of Shadowburn + if (pVictim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT)) + crit_chance+=(*i)->GetModifier()->m_amount; + break; + case 7997: // Renewed Hope + case 7998: + if (pVictim->HasAura(6788)) + crit_chance+=(*i)->GetModifier()->m_amount; + break; + case 21: // Test of Faith + case 6935: + case 6918: + if (pVictim->GetHealth() < pVictim->GetMaxHealth()/2) + crit_chance+=(*i)->GetModifier()->m_amount; + break; + default: + break; + } + } + // Custom crit by class + switch(spellProto->SpellFamilyName) + { + case SPELLFAMILY_PALADIN: + // Sacred Shield + if (spellProto->SpellFamilyFlags[0] & 0x40000000) { - case 849: crit_chance+= 10.0f; break; //Shatter Rank 1 - case 910: crit_chance+= 20.0f; break; //Shatter Rank 2 - case 911: crit_chance+= 30.0f; break; //Shatter Rank 3 - case 912: crit_chance+= 40.0f; break; //Shatter Rank 4 - case 913: crit_chance+= 50.0f; break; //Shatter Rank 5 + Aura *aura = pVictim->GetDummyAura(58597); + if (aura && aura->GetCasterGUID() == GetGUID()) + crit_chance+=aura->GetModifier()->m_amount; + break; } - } + break; + case SPELLFAMILY_SHAMAN: + // Lava Burst + if (spellProto->SpellFamilyFlags[1] & 0x00001000) + { + if (Aura *flameShock = pVictim->GetAura(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_SHAMAN, 10000000, 0,0, GetGUID())) + { + // Consume shock aura if not have Glyph of Flame Shock + if (!GetAura(55447, 0)) + pVictim->RemoveAurasByCasterSpell(flameShock->GetId(), GetGUID()); + return true; + } + break; + } + break; + } } break; @@ -9075,7 +8368,6 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM if (pVictim) { crit_chance = GetUnitCriticalChance(attackType, pVictim); - crit_chance+= (int32(GetMaxSkillValueForLevel(pVictim)) - int32(pVictim->GetDefenseSkillValue(this))) * 0.04f; crit_chance+= GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, schoolMask); } break; @@ -9094,7 +8386,7 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM return false; } -uint32 Unit::SpellCriticalBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim) +uint32 Unit::SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim) { // Calculate critical bonus int32 crit_bonus; @@ -9126,15 +8418,49 @@ uint32 Unit::SpellCriticalBonus(SpellEntry const *spellProto, uint32 damage, Uni return damage; } -uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, Unit *pVictim) +uint32 Unit::SpellCriticalHealingBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim) +{ + // Calculate critical bonus + int32 crit_bonus; + switch(spellProto->DmgClass) + { + case SPELL_DAMAGE_CLASS_MELEE: // for melee based spells is 100% + case SPELL_DAMAGE_CLASS_RANGED: + // TODO: write here full calculation for melee/ranged spells + crit_bonus = damage; + break; + default: + crit_bonus = damage / 2; // for spells is 50% + break; + } + + + if(pVictim) + { + uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); + crit_bonus = int32(crit_bonus * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask)); + } + + if(crit_bonus > 0) + damage += crit_bonus; + + damage = int32(float(damage) * GetTotalAuraMultiplier(SPELL_AURA_MOD_CRITICAL_HEALING_AMOUNT)); + + return damage; +} + +uint32 Unit::SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack) { + // No heal amount for this class spells + if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE) + return healamount; + // For totems get healing bonus from owner (statue isn't totem in fact) if( GetTypeId()==TYPEID_UNIT && ((Creature*)this)->isTotem() && ((Totem*)this)->GetTotemType()!=TOTEM_STATUE) if(Unit* owner = GetOwner()) - return owner->SpellHealingBonus(spellProto, healamount, damagetype, pVictim); - - // Healing Done + return owner->SpellHealingBonus(pVictim, spellProto, healamount, damagetype, stack); + // TODO: to be deleted // These Spells are doing fixed amount of healing (TODO found less hack-like check) if (spellProto->Id == 15290 || spellProto->Id == 39373 || spellProto->Id == 33778 || spellProto->Id == 379 || @@ -9143,86 +8469,91 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, spellProto->Id == 34299) return healamount; - int32 AdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto)); - uint32 CastingTime = GetSpellCastTime(spellProto); + // Healing Done + // Taken/Done total percent damage auras + float DoneTotalMod = 1.0f; + float TakenTotalMod = 1.0f; + int32 DoneTotal = 0; + int32 TakenTotal = 0; - // Healing Taken - AdvertisedBenefit += SpellBaseHealingBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); + // Healing done percent + AuraList const& mHealingDonePct = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT); + for(AuraList::const_iterator i = mHealingDonePct.begin();i != mHealingDonePct.end(); ++i) + DoneTotalMod *= (100.0f + (*i)->GetModifier()->m_amount) / 100.0f; - // Blessing of Light dummy effects healing taken from Holy Light and Flash of Light - if (spellProto->SpellFamilyName == SPELLFAMILY_PALADIN && (spellProto->SpellFamilyFlags & 0x00000000C0000000LL)) + // done scripted mod (take it from owner) + Unit *owner = GetOwner(); + if (!owner) owner = this; + AuraList const& mOverrideClassScript= owner->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); + for(AuraList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) { - AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); - for(AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) + if (!(*i)->isAffectedOnSpell(spellProto)) + continue; + switch((*i)->GetModifier()->m_miscvalue) { - if((*i)->GetSpellProto()->SpellVisual == 9180) + case 4415: // Increased Rejuvenation Healing + case 4953: + case 3736: // Hateful Totem of the Third Wind / Increased Lesser Healing Wave / LK Arena (4/5/6) Totem of the Third Wind / Savage Totem of the Third Wind + DoneTotal+=(*i)->GetModifier()->m_amount; + break; + case 7997: // Renewed Hope + case 7998: + if (pVictim->HasAura(6788)) + DoneTotalMod *=((*i)->GetModifier()->m_amount + 100.0f)/100.0f; + break; + case 21: // Test of Faith + case 6935: + case 6918: + if (pVictim->GetHealth() < pVictim->GetMaxHealth()/2) + DoneTotalMod *=((*i)->GetModifier()->m_amount + 100.0f)/100.0f; + break; + case 7798: // Glyph of Regrowth { - // Flash of Light - if ((spellProto->SpellFamilyFlags & 0x0000000040000000LL) && (*i)->GetEffIndex() == 1) - AdvertisedBenefit += (*i)->GetModifier()->m_amount; - // Holy Light - else if ((spellProto->SpellFamilyFlags & 0x0000000080000000LL) && (*i)->GetEffIndex() == 0) - AdvertisedBenefit += (*i)->GetModifier()->m_amount; + if (pVictim->GetAura(SPELL_AURA_PERIODIC_HEAL, SPELLFAMILY_DRUID, 0x40)) + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + break; } - } - } - - float ActualBenefit = 0.0f; - - if (AdvertisedBenefit != 0) - { - // Healing over Time spells - float DotFactor = 1.0f; - if(damagetype == DOT) - { - int32 DotDuration = GetSpellDuration(spellProto); - if(DotDuration > 0) + case 8477: // Nourish Heal Boost { - // 200% limit - if(DotDuration > 30000) DotDuration = 30000; - if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; - int x = 0; - for(int j = 0; j < 3; j++) + int32 stepPercent = (*i)->GetModifier()->m_amount; + int32 modPercent = 0; + AuraMap const& victimAuras = pVictim->GetAuras(); + for (AuraMap::const_iterator itr = victimAuras.begin(); itr != victimAuras.end(); ++itr) { - if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_HEAL || - spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) - { - x = j; - break; - } + if (itr->second->GetCasterGUID()!=GetGUID()) + continue; + SpellEntry const* m_spell = itr->second->GetSpellProto(); + if ( m_spell->SpellFamilyName != SPELLFAMILY_DRUID || + !(m_spell->SpellFamilyFlags[1] & 0x00000010 || m_spell->SpellFamilyFlags[0] & 0x50)) + continue; + modPercent += stepPercent * itr->second->GetStackAmount(); } - int DotTicks = 6; - if(spellProto->EffectAmplitude[x] != 0) - DotTicks = DotDuration / spellProto->EffectAmplitude[x]; - if(DotTicks) - AdvertisedBenefit /= DotTicks; + DoneTotalMod *= (modPercent+100.0f)/100.0f; + break; } - } - - // distribute healing to all effects, reduce AoE damage - CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); - - // 0% bonus for damage and healing spells for leech spells from healing bonus - for(int j = 0; j < 3; ++j) - { - if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || - spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) + case 7871: // Glyph of Lesser Healing Wave { - CastingTime = 0; + if (pVictim->GetAura(SPELL_AURA_DUMMY, SPELLFAMILY_SHAMAN, 0 , 0x00000400, 0, GetGUID())) + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; break; } + default: + break; } + } - // Exception + /*// Exception switch (spellProto->SpellFamilyName) { - case SPELLFAMILY_SHAMAN: + case SPELLFAMILY_GENERIC: // Healing stream from totem (add 6% per tick from hill bonus owner) - if (spellProto->SpellFamilyFlags & 0x000000002000LL) + // Possibly need do it on apply dummy aura + if (spellProto->Id == 52042) CastingTime = 210; + break; + case SPELLFAMILY_SHAMAN: // Earth Shield 30% per charge - else if (spellProto->SpellFamilyFlags & 0x40000000000LL) + if (spellProto->SpellFamilyFlags & 0x40000000000LL) CastingTime = 1050; break; case SPELLFAMILY_DRUID: @@ -9266,64 +8597,136 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, case SPELLFAMILY_HUNTER: CastingTime = 0; break; - } - - float LvlPenalty = CalculateLevelPenalty(spellProto); - - // Spellmod SpellDamage - //float SpellModSpellDamage = 100.0f; - float CoefficientPtc = ((float)CastingTime/3500.0f)*DotFactor*100.0f; + }*/ - if(Player* modOwner = GetSpellModOwner()) - //modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,SpellModSpellDamage); - modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_SPELL_BONUS_DAMAGE,CoefficientPtc); + // Taken/Done fixed damage bonus auras + int32 DoneAdvertisedBenefit = SpellBaseHealingBonus(GetSpellSchoolMask(spellProto)); + int32 TakenAdvertisedBenefit = SpellBaseHealingBonusForVictim(GetSpellSchoolMask(spellProto), pVictim); - //SpellModSpellDamage /= 100.0f; - CoefficientPtc /= 100.0f; + // Check for table values + SpellBonusEntry const* bonus = spellmgr.GetSpellBonusData(spellProto->Id); + float coeff; + if (bonus) + { + if (damagetype == DOT) + coeff = bonus->dot_damage; + else + coeff = bonus->direct_damage; + if (bonus->ap_bonus) + DoneTotal+=bonus->ap_bonus * GetTotalAttackPowerValue(BASE_ATTACK) * stack; + } + // Default calculation + else if (DoneAdvertisedBenefit || TakenAdvertisedBenefit) + { + // Damage Done from spell damage bonus + int32 CastingTime = !IsChanneledSpell(spellProto) ? GetSpellCastTime(spellProto) : GetSpellDuration(spellProto); + if (IsChanneledSpell(spellProto)) + ModSpellCastTime(spellProto, CastingTime); + // Damage over Time spells bonus calculation + float DotFactor = 1.0f; + if(damagetype == DOT) + { + int32 DotDuration = GetSpellDuration(spellProto); + //apply casting time mods for channeled spells + if (IsChanneledSpell(spellProto)) + ModSpellCastTime(spellProto, DotDuration); + // 200% limit + if(DotDuration > 0) + { + if(DotDuration > 30000) DotDuration = 30000; + if(!IsChanneledSpell(spellProto)) DotFactor = DotDuration / 15000.0f; + int x = 0; + for(int j = 0; j < 3; j++) + { + if( spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && ( + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_DAMAGE || + spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH) ) + { + x = j; + break; + } + } + int32 DotTicks = 6; + if(spellProto->EffectAmplitude[x] != 0) + DotTicks = DotDuration / spellProto->EffectAmplitude[x]; + if(DotTicks) + { + DoneAdvertisedBenefit /= DotTicks*int32(stack); + TakenAdvertisedBenefit /= DotTicks*int32(stack); + } + } + } + // Distribute Damage over multiple effects, reduce by AoE + CastingTime = GetCastingTimeForBonus( spellProto, damagetype, CastingTime ); + // 50% for damage and healing spells for leech spells from damage bonus and 0% from healing + for(int j = 0; j < 3; ++j) + { + if( spellProto->Effect[j] == SPELL_EFFECT_HEALTH_LEECH || + spellProto->Effect[j] == SPELL_EFFECT_APPLY_AURA && spellProto->EffectApplyAuraName[j] == SPELL_AURA_PERIODIC_LEECH ) + { + CastingTime /= 2; + break; + } + } + coeff = (CastingTime / 3500.0f) * DotFactor; + } - //ActualBenefit = (float)AdvertisedBenefit * ((float)CastingTime / 3500.0f) * DotFactor * SpellModSpellDamage * LvlPenalty; - ActualBenefit = (float)AdvertisedBenefit * CoefficientPtc * LvlPenalty; + float coeff2 = CalculateLevelPenalty(spellProto) * 1.88f * stack; + TakenTotal+= TakenAdvertisedBenefit * coeff * coeff2; + if(Player* modOwner = GetSpellModOwner()) + { + coeff *= 100.0f; + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_SPELL_BONUS_DAMAGE, coeff); + coeff /= 100.0f; } + DoneTotal += DoneAdvertisedBenefit * coeff * coeff2; // use float as more appropriate for negative values and percent applying - float heal = healamount + ActualBenefit; - - // TODO: check for ALL/SPELLS type - // Healing done percent - AuraList const& mHealingDonePct = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT); - for(AuraList::const_iterator i = mHealingDonePct.begin();i != mHealingDonePct.end(); ++i) - heal *= (100.0f + (*i)->GetModifierValue()) / 100.0f; - + float heal = (healamount + DoneTotal)*DoneTotalMod; // apply spellmod to Done amount if(Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal); + // Taken mods // Healing Wave cast - if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags & 0x0000000000000040LL) + if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[0] & 0x40) { - // Search for Healing Way on Victim (stack up to 3 time) - int32 pctMod = 0; + // Search for Healing Way on Victim Unit::AuraList const& auraDummy = pVictim->GetAurasByType(SPELL_AURA_DUMMY); for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr!=auraDummy.end(); ++itr) if((*itr)->GetId() == 29203) - pctMod += (*itr)->GetModifier()->m_amount; - // Apply bonus - if (pctMod) - heal = heal * (100 + pctMod) / 100; + TakenTotalMod *= ((*itr)->GetModifier()->m_amount+100.0f) / 100.0f; } // Healing taken percent float minval = pVictim->GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT); if(minval) - heal *= (100.0f + minval) / 100.0f; + TakenTotalMod *= (100.0f + minval) / 100.0f; float maxval = pVictim->GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT); if(maxval) - heal *= (100.0f + maxval) / 100.0f; + TakenTotalMod *= (100.0f + maxval) / 100.0f; + + if(damagetype==DOT) + { + // Healing over time taken percent + float minval_hot = GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT); + if(minval_hot) + TakenTotalMod *= (100.0f + minval_hot) / 100.0f; + + float maxval_hot = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT); + if(maxval_hot) + TakenTotalMod *= (100.0f + maxval_hot) / 100.0f; + } + + AuraList const& mHealingGet= pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING_RECEIVED); + for(AuraList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i) + if (GetGUID()==(*i)->GetCasterGUID() && (*i)->isAffectedOnSpell(spellProto) ) + TakenTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f; - if (heal < 0) heal = 0; + heal = (heal + TakenTotal) * TakenTotalMod; - return uint32(heal); + return heal < 0 ? 0 : uint32(heal); } int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask) @@ -9333,25 +8736,28 @@ int32 Unit::SpellBaseHealingBonus(SpellSchoolMask schoolMask) AuraList const& mHealingDone = GetAurasByType(SPELL_AURA_MOD_HEALING_DONE); for(AuraList::const_iterator i = mHealingDone.begin();i != mHealingDone.end(); ++i) if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0) - AdvertisedBenefit += (*i)->GetModifierValue(); + AdvertisedBenefit += (*i)->GetModifier()->m_amount; // Healing bonus of spirit, intellect and strength if (GetTypeId() == TYPEID_PLAYER) { + // Base value + AdvertisedBenefit +=((Player*)this)->GetBaseSpellHealingBonus(); + // Healing bonus from stats AuraList const& mHealingDoneOfStatPercent = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT); for(AuraList::const_iterator i = mHealingDoneOfStatPercent.begin();i != mHealingDoneOfStatPercent.end(); ++i) { // stat used dependent from misc value (stat index) Stats usedStat = Stats((*i)->GetSpellProto()->EffectMiscValue[(*i)->GetEffIndex()]); - AdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifierValue() / 100.0f); + AdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifier()->m_amount / 100.0f); } // ... and attack power AuraList const& mHealingDonebyAP = GetAurasByType(SPELL_AURA_MOD_SPELL_HEALING_OF_ATTACK_POWER); for(AuraList::const_iterator i = mHealingDonebyAP.begin();i != mHealingDonebyAP.end(); ++i) if ((*i)->GetModifier()->m_miscvalue & schoolMask) - AdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifierValue() / 100.0f); + AdvertisedBenefit += int32(GetTotalAttackPowerValue(BASE_ATTACK) * (*i)->GetModifier()->m_amount / 100.0f); } return AdvertisedBenefit; } @@ -9362,11 +8768,11 @@ int32 Unit::SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVi AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_HEALING); for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i) if(((*i)->GetModifier()->m_miscvalue & schoolMask) != 0) - AdvertisedBenefit += (*i)->GetModifierValue(); + AdvertisedBenefit += (*i)->GetModifier()->m_amount; return AdvertisedBenefit; } -bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask, bool useCharges) +bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask) { //If m_immuneToSchool type contain this school type, IMMUNE damage. SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL]; @@ -9383,7 +8789,7 @@ bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask, bool useCharges) return false; } -bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) +bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo) { if (!spellInfo) return false; @@ -9407,7 +8813,7 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; for(SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) { - if(itr->type == spellInfo->Mechanic) + if(itr->type & (1<<spellInfo->Mechanic)) { return true; } @@ -9425,18 +8831,39 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) return false; } -bool Unit::IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const +bool Unit::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const { + if (!spellInfo) + return false; //If m_immuneToEffect type contain this effect type, IMMUNE effect. + uint32 effect = spellInfo->Effect[index]; SpellImmuneList const& effectList = m_spellImmune[IMMUNITY_EFFECT]; for (SpellImmuneList::const_iterator itr = effectList.begin(); itr != effectList.end(); ++itr) if(itr->type == effect) return true; - SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; - for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) - if(itr->type == mechanic) - return true; + if(uint32 mechanic = spellInfo->EffectMechanic[index]) + { + SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC]; + for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr) + if(itr->type & 1<<(spellInfo->EffectMechanic[index])) + return true; + } + + if(uint32 aura = spellInfo->EffectApplyAuraName[index]) + { + SpellImmuneList const& list = m_spellImmune[IMMUNITY_STATE]; + for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr) + if(itr->type == aura) + return true; + // Check for immune to application of harmful magical effects + AuraList const& immuneAuraApply = GetAurasByType(SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL); + for(AuraList::const_iterator iter = immuneAuraApply.begin(); iter != immuneAuraApply.end(); ++iter) + if (spellInfo->Dispel == DISPEL_MAGIC && // Magic debuff + ((*iter)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellInfo)) && // Check school + !IsPositiveEffect(spellInfo->Id, index)) // Harmful + return true; + } return false; } @@ -9474,7 +8901,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT AuraList const& mDamageDoneCreature = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_CREATURE); for(AuraList::const_iterator i = mDamageDoneCreature.begin();i != mDamageDoneCreature.end(); ++i) if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) - DoneFlatBenefit += (*i)->GetModifierValue(); + DoneFlatBenefit += (*i)->GetModifier()->m_amount; // ..done // SPELL_AURA_MOD_DAMAGE_DONE included in weapon damage @@ -9489,7 +8916,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT AuraList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS); for(AuraList::const_iterator i = mCreatureAttackPower.begin();i != mCreatureAttackPower.end(); ++i) if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) - APbonus += (*i)->GetModifierValue(); + APbonus += (*i)->GetModifier()->m_amount; } else { @@ -9499,7 +8926,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT AuraList const& mCreatureAttackPower = GetAurasByType(SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS); for(AuraList::const_iterator i = mCreatureAttackPower.begin();i != mCreatureAttackPower.end(); ++i) if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) - APbonus += (*i)->GetModifierValue(); + APbonus += (*i)->GetModifier()->m_amount; } if (APbonus!=0) // Can be negative @@ -9524,7 +8951,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT AuraList const& mDamageTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_TAKEN); for(AuraList::const_iterator i = mDamageTaken.begin();i != mDamageTaken.end(); ++i) if((*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask()) - TakenFlatBenefit += (*i)->GetModifierValue(); + TakenFlatBenefit += (*i)->GetModifier()->m_amount; if(attType!=RANGED_ATTACK) TakenFlatBenefit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN); @@ -9532,8 +8959,8 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT TakenFlatBenefit += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN); // Done/Taken total percent damage auras - float DoneTotalMod = 1; - float TakenTotalMod = 1; + float DoneTotalMod = 1.0f; + float TakenTotalMod = 1.0f; // ..done // SPELL_AURA_MOD_DAMAGE_PERCENT_DONE included in weapon damage @@ -9542,13 +8969,13 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT AuraList const& mDamageDoneVersus = GetAurasByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS); for(AuraList::const_iterator i = mDamageDoneVersus.begin();i != mDamageDoneVersus.end(); ++i) if(creatureTypeMask & uint32((*i)->GetModifier()->m_miscvalue)) - DoneTotalMod *= ((*i)->GetModifierValue()+100.0f)/100.0f; + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; // ..taken AuraList const& mModDamagePercentTaken = pVictim->GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN); for(AuraList::const_iterator i = mModDamagePercentTaken.begin(); i != mModDamagePercentTaken.end(); ++i) if((*i)->GetModifier()->m_miscvalue & GetMeleeDamageSchoolMask()) - TakenTotalMod *= ((*i)->GetModifierValue()+100.0f)/100.0f; + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; // .. taken pct: dummy auras AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); @@ -9573,7 +9000,7 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT if(spellProto==NULL) break; // Should increase Shred (initial Damage of Lacerate and Rake handled in Spell::EffectSchoolDMG) - if(spellProto->SpellFamilyName==SPELLFAMILY_DRUID && (spellProto->SpellFamilyFlags==0x00008000LL)) + if(spellProto->SpellFamilyName==SPELLFAMILY_DRUID && spellProto->SpellFamilyFlags.IsEqual (0x00008000,0,0)) TakenTotalMod *= (100.0f+(*i)->GetModifier()->m_amount)/100.0f; break; } @@ -9606,13 +9033,13 @@ void Unit::MeleeDamageBonus(Unit *pVictim, uint32 *pdamage,WeaponAttackType attT { AuraList const& mModMeleeDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_MELEE_DAMAGE_TAKEN_PCT); for(AuraList::const_iterator i = mModMeleeDamageTakenPercent.begin(); i != mModMeleeDamageTakenPercent.end(); ++i) - TakenTotalMod *= ((*i)->GetModifierValue()+100.0f)/100.0f; + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; } else { AuraList const& mModRangedDamageTakenPercent = pVictim->GetAurasByType(SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT); for(AuraList::const_iterator i = mModRangedDamageTakenPercent.begin(); i != mModRangedDamageTakenPercent.end(); ++i) - TakenTotalMod *= ((*i)->GetModifierValue()+100.0f)/100.0f; + TakenTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; } float tmpDamage = float(int32(*pdamage) + DoneFlatBenefit) * DoneTotalMod; @@ -9735,7 +9162,7 @@ void Unit::Unmount() if(GetTypeId() == TYPEID_PLAYER && IsInWorld() && ((Player*)this)->GetTemporaryUnsummonedPetNumber() && isAlive()) { Pet* NewPet = new Pet; - if(!NewPet->LoadPetFromDB(this, 0, ((Player*)this)->GetTemporaryUnsummonedPetNumber(), true)) + if(!NewPet->LoadPetFromDB((Player*)this, 0, ((Player*)this)->GetTemporaryUnsummonedPetNumber(), true)) delete NewPet; ((Player*)this)->SetTemporaryUnsummonedPetNumber(0); @@ -9767,7 +9194,7 @@ void Unit::SetInCombatWith(Unit* enemy) void Unit::CombatStart(Unit* target) { if(!target->IsStandState()/* && !target->hasUnitState(UNIT_STAT_STUNNED)*/) - target->SetStandState(PLAYER_STATE_NONE); + target->SetStandState(UNIT_STAND_STATE_STAND); if(!target->isInCombat() && target->GetTypeId() != TYPEID_PLAYER && !((Creature*)target)->HasReactState(REACT_PASSIVE) && ((Creature*)target)->AI()) @@ -10051,7 +9478,7 @@ void Unit::DestroyForNearbyPlayers() std::list<Unit*> targets; Trinity::AnyUnitInObjectRangeCheck check(this, World::GetMaxVisibleDistance()); - Trinity::UnitListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(targets, check); + Trinity::UnitListSearcher<Trinity::AnyUnitInObjectRangeCheck> searcher(this, targets, check); VisitNearbyWorldObject(World::GetMaxVisibleDistance(), searcher); for(std::list<Unit*>::iterator iter = targets.begin(); iter != targets.end(); ++iter) if(*iter != this && (*iter)->GetTypeId() == TYPEID_PLAYER @@ -10175,38 +9602,37 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) propagateSpeedChange(); - // Send speed change packet only for player - if (GetTypeId()!=TYPEID_PLAYER) - return; - WorldPacket data; if(!forced) { switch(mtype) { case MOVE_WALK: - data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_RUN: - data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_RUN_BACK: - data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_SWIM: - data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_SWIM_BACK: - data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_TURN_RATE: - data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_FLIGHT: - data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+2+4+4+4+4+4+4+4); break; case MOVE_FLIGHT_BACK: - data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); + break; + case MOVE_PITCH_RATE: + data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8+4+2+4+4+4+4+4+4+4); break; default: sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype); @@ -10214,22 +9640,26 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) } data.append(GetPackGUID()); - data << uint32(0); //movement flags - data << uint8(0); //unk + data << uint32(0); // movement flags + data << uint16(0); // unk flags data << uint32(getMSTime()); data << float(GetPositionX()); data << float(GetPositionY()); data << float(GetPositionZ()); data << float(GetOrientation()); - data << uint32(0); //flag unk + data << uint32(0); // fall time data << float(GetSpeed(mtype)); SendMessageToSet( &data, true ); } else { - // register forced speed changes for WorldSession::HandleForceSpeedChangeAck - // and do it only for real sent packets and use run for run/mounted as client expected - ++((Player*)this)->m_forced_speed_changes[mtype]; + if(GetTypeId() == TYPEID_PLAYER) + { + // register forced speed changes for WorldSession::HandleForceSpeedChangeAck + // and do it only for real sent packets and use run for run/mounted as client expected + ++((Player*)this)->m_forced_speed_changes[mtype]; + } + switch(mtype) { case MOVE_WALK: @@ -10256,6 +9686,9 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) case MOVE_FLIGHT_BACK: data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16); break; + case MOVE_PITCH_RATE: + data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16); + break; default: sLog.outError("Unit::SetSpeed: Unsupported move type (%d), data not sent to client.",mtype); return; @@ -10345,6 +9778,10 @@ bool Unit::CanHaveThreatList() const if( ((Creature*)this)->isTotem() ) return false; + // vehicles can not have threat list + if( ((Creature*)this)->isVehicle() ) + return false; + // pets can not have a threat list, unless they are controlled by a creature if( ((Creature*)this)->isPet() && IS_PLAYER_GUID(((Pet*)this)->GetOwnerGUID()) ) return false; @@ -10449,18 +9886,44 @@ Unit* Creature::SelectVictim() //or who does not have threat (totem/pet/critter) //otherwise enterevademode every update - Unit* target = NULL; - if(!m_ThreatManager.isThreatListEmpty()) + + Unit* target = NULL; + // First checking if we have some taunt on us + const AuraList& tauntAuras = GetAurasByType(SPELL_AURA_MOD_TAUNT); + if ( !tauntAuras.empty() ) { - if(!HasAuraType(SPELL_AURA_MOD_TAUNT)) + Unit* caster; + + // The last taunt aura caster is alive an we are happy to attack him + if ( (caster = tauntAuras.back()->GetCaster()) && caster->isAlive() ) + return getVictim(); + else if (tauntAuras.size() > 1) { - target = m_ThreatManager.getHostilTarget(); + // We do not have last taunt aura caster but we have more taunt auras, + // so find first available target + + // Auras are pushed_back, last caster will be on the end + AuraList::const_iterator aura = --tauntAuras.end(); + do + { + --aura; + if ( (caster = (*aura)->GetCaster()) && + caster->IsInMap(this) && canAttack(caster) && caster->isInAccessiblePlaceFor((Creature*)this) ) + { + target = caster; + break; + } + }while (aura != tauntAuras.begin()); } else target = getVictim(); } + if ( !target && !m_ThreatManager.isThreatListEmpty() ) + // No taunt aura or taunt aura caster is dead standart target selection + target = m_ThreatManager.getHostilTarget(); + if(target) { if(!hasUnitState(UNIT_STAT_STUNNED)) @@ -10532,8 +9995,11 @@ int32 Unit::CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_inde int32 randomPoints = int32(spellProto->EffectDieSides[effect_index] + level * randomPointsPerLevel); float comboDamage = spellProto->EffectPointsPerComboPoint[effect_index]; - // prevent random generator from getting confused by spells casted with Unit::CastCustomSpell - int32 randvalue = spellProto->EffectBaseDice[effect_index] >= randomPoints ? spellProto->EffectBaseDice[effect_index]:irand(spellProto->EffectBaseDice[effect_index], randomPoints); + // range can have possitive and negative values, so order its for irand + int32 randvalue = int32(spellProto->EffectBaseDice[effect_index]) >= randomPoints + ? irand(randomPoints, int32(spellProto->EffectBaseDice[effect_index])) + : irand(int32(spellProto->EffectBaseDice[effect_index]), randomPoints); + int32 value = basePoints + randvalue; //random damage if(comboDamage != 0 && unitPlayer /*&& target && (target->GetGUID() == unitPlayer->GetComboTarget())*/) @@ -10566,7 +10032,7 @@ int32 Unit::CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_inde return value; } -int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_index, Unit const* target) +int32 Unit::CalcSpellDuration(SpellEntry const* spellProto) { Player* unitPlayer = (GetTypeId() == TYPEID_PLAYER) ? (Player*)this : NULL; @@ -10582,14 +10048,24 @@ int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_in else duration = minduration; - if (duration > 0) + return duration; +} + +int32 Unit::ModSpellDuration(SpellEntry const* spellProto, uint8 effect_index, Unit const* target, int32 duration) +{ + //don't mod permament auras duration + if (duration<0) + return duration; + + //cut duration only of negative effects + if (!IsPositiveEffect(spellProto->Id, effect_index) ) { int32 mechanic = GetEffectMechanic(spellProto, effect_index); + // Find total mod value (negative bonus) int32 durationMod_always = target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD, mechanic); // Find max mod (negative bonus) int32 durationMod_not_stack = target->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK, mechanic); - int32 durationMod = 0; // Select strongest negative mod if (durationMod_always > durationMod_not_stack) @@ -10598,12 +10074,41 @@ int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_in durationMod = durationMod_always; if (durationMod != 0) - duration = int32(int64(duration) * (100+durationMod) /100); + duration = int32( float (duration) * float(100.0f+durationMod) /100.0f); + + // there are only negative mods currently + durationMod_always =target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL, spellProto->Dispel); + durationMod_not_stack=target->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MOD_AURA_DURATION_BY_DISPEL_NOT_STACK, spellProto->Dispel); + + durationMod=0; + if (durationMod_always > durationMod_not_stack) + durationMod += durationMod_not_stack; + else + durationMod += durationMod_always; - if (duration < 0) duration = 0; + if (durationMod != 0) + duration = int32( float (duration) * float(100.0f+durationMod) /100.0f); } + //else positive mods here, there are no currently + //when there will be, change GetTotalAuraModifierByMiscValue to GetTotalPositiveAuraModifierByMiscValue + return duration>0 ? duration : 0; +} - return duration; +void Unit::ModSpellCastTime(SpellEntry const* spellProto, int32 & castTime) +{ + if (!spellProto || castTime<0) + return; + //called from caster + if(Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CASTING_TIME, castTime); + + if( !(spellProto->Attributes & (SPELL_ATTR_UNK4|SPELL_ATTR_UNK5)) ) + castTime = int32( float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED)); + else + { + if (spellProto->Attributes & SPELL_ATTR_RANGED && !(spellProto->AttributesEx2 & SPELL_ATTR_EX2_AUTOREPEAT_FLAG)) + castTime = int32 (float(castTime) * m_modAttackSpeedPct[RANGED_ATTACK]); + } } DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) @@ -10637,21 +10142,15 @@ DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) void Unit::IncrDiminishing(DiminishingGroup group) { // Checking for existing in the table - bool IsExist = false; for(Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) { if(i->DRGroup != group) continue; - - IsExist = true; if(i->hitCount < DIMINISHING_LEVEL_IMMUNE) i->hitCount += 1; - - break; + return; } - - if(!IsExist) - m_Diminishing.push_back(DiminishingReturn(group,getMSTime(),DIMINISHING_LEVEL_2)); + m_Diminishing.push_back(DiminishingReturn(group,getMSTime(),DIMINISHING_LEVEL_2)); } void Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration,Unit* caster,DiminishingLevels Level) @@ -10700,13 +10199,15 @@ void Unit::ApplyDiminishingAura( DiminishingGroup group, bool apply ) if(i->DRGroup != group) continue; - i->hitTime = getMSTime(); - if(apply) i->stack += 1; else if(i->stack) + { i->stack -= 1; - + // Remember time after last aura from group removed + if (i->stack == 0) + i->hitTime = getMSTime(); + } break; } } @@ -10788,7 +10289,9 @@ bool Unit::HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, f case UNIT_MOD_RAGE: case UNIT_MOD_FOCUS: case UNIT_MOD_ENERGY: - case UNIT_MOD_HAPPINESS: UpdateMaxPower(GetPowerTypeByAuraGroup(unitMod)); break; + case UNIT_MOD_HAPPINESS: + case UNIT_MOD_RUNE: + case UNIT_MOD_RUNIC_POWER: UpdateMaxPower(GetPowerTypeByAuraGroup(unitMod)); break; case UNIT_MOD_RESISTANCE_HOLY: case UNIT_MOD_RESISTANCE_FIRE: @@ -10901,32 +10404,36 @@ Stats Unit::GetStatByAuraGroup(UnitMods unitMod) const Powers Unit::GetPowerTypeByAuraGroup(UnitMods unitMod) const { - Powers power = POWER_MANA; - switch(unitMod) { - case UNIT_MOD_MANA: power = POWER_MANA; break; - case UNIT_MOD_RAGE: power = POWER_RAGE; break; - case UNIT_MOD_FOCUS: power = POWER_FOCUS; break; - case UNIT_MOD_ENERGY: power = POWER_ENERGY; break; - case UNIT_MOD_HAPPINESS: power = POWER_HAPPINESS; break; - - default: - break; + case UNIT_MOD_MANA: return POWER_MANA; + case UNIT_MOD_RAGE: return POWER_RAGE; + case UNIT_MOD_FOCUS: return POWER_FOCUS; + case UNIT_MOD_ENERGY: return POWER_ENERGY; + case UNIT_MOD_HAPPINESS: return POWER_HAPPINESS; + case UNIT_MOD_RUNE: return POWER_RUNE; + case UNIT_MOD_RUNIC_POWER:return POWER_RUNIC_POWER; } - return power; + return POWER_MANA; } float Unit::GetTotalAttackPowerValue(WeaponAttackType attType) const { - UnitMods unitMod = (attType == RANGED_ATTACK) ? UNIT_MOD_ATTACK_POWER_RANGED : UNIT_MOD_ATTACK_POWER; - - float val = GetTotalAuraModValue(unitMod); - if(val < 0.0f) - val = 0.0f; - - return val; + if (attType == RANGED_ATTACK) + { + int32 ap = GetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER) + GetInt32Value(UNIT_FIELD_RANGED_ATTACK_POWER_MODS); + if (ap < 0) + return 0.0f; + return ap * (1.0f + GetFloatValue(UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER)); + } + else + { + int32 ap = GetInt32Value(UNIT_FIELD_ATTACK_POWER) + GetInt32Value(UNIT_FIELD_ATTACK_POWER_MODS); + if (ap < 0) + return 0.0f; + return ap * (1.0f + GetFloatValue(UNIT_FIELD_ATTACK_POWER_MULTIPLIER)); + } } float Unit::GetWeaponDamageRange(WeaponAttackType attType ,WeaponDamageRange type) const @@ -11014,6 +10521,12 @@ void Unit::SetPower(Powers power, uint32 val) SetStatInt32Value(UNIT_FIELD_POWER1 + power, val); + WorldPacket data(SMSG_POWER_UPDATE); + data.append(GetPackGUID()); + data << uint8(power); + data << uint32(val); + SendMessageToSet(&data, GetTypeId() == TYPEID_PLAYER ? true : false); + // group update if(GetTypeId() == TYPEID_PLAYER) { @@ -11127,6 +10640,7 @@ uint32 Unit::GetCreatePowers( Powers power ) const case POWER_FOCUS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 100); case POWER_ENERGY: return 100; case POWER_HAPPINESS: return (GetTypeId()==TYPEID_PLAYER || !((Creature const*)this)->isPet() || ((Pet const*)this)->getPetType()!=HUNTER_PET ? 0 : 1050000); + case POWER_RUNIC_POWER: return 1000; } return 0; @@ -11214,7 +10728,7 @@ void CharmInfo::InitEmptyActionBar(bool withAttack) for(uint32 x = 0; x < 10; ++x) { - PetActionBar[x].Type = ACT_CAST; + PetActionBar[x].Type = ACT_PASSIVE; PetActionBar[x].SpellOrAction = 0; } if (withAttack) @@ -11230,13 +10744,20 @@ void CharmInfo::InitPossessCreateSpells() InitEmptyActionBar(); if(m_unit->GetTypeId() == TYPEID_UNIT) { - for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) + /*for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) { uint32 spellid = ((Creature*)m_unit)->m_spells[i]; if(IsPassiveSpell(spellid)) m_unit->CastSpell(m_unit, spellid, true); else AddSpellToAB(0, spellid, ACT_CAST); + }*/ + for(uint32 x = 0; x < CREATURE_MAX_SPELLS; ++x) + { + if (IsPassiveSpell(((Creature*)m_unit)->m_spells[x])) + m_unit->CastSpell(m_unit, ((Creature*)m_unit)->m_spells[x], true); + else + AddSpellToAB(0, ((Creature*)m_unit)->m_spells[x], ACT_PASSIVE); } } } @@ -11280,7 +10801,7 @@ void CharmInfo::InitCharmCreateSpells() if(onlyselfcast || !IsPositiveSpell(spellId)) //only self cast and spells versus enemies are autocastable newstate = ACT_DISABLED; else - newstate = ACT_CAST; + newstate = ACT_PASSIVE; AddSpellToAB(0, spellId, newstate); } @@ -11291,7 +10812,7 @@ bool CharmInfo::AddSpellToAB(uint32 oldid, uint32 newid, ActiveStates newstate) { for(uint8 i = 0; i < 10; i++) { - if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_CAST) && PetActionBar[i].SpellOrAction == oldid) + if((PetActionBar[i].Type == ACT_DISABLED || PetActionBar[i].Type == ACT_ENABLED || PetActionBar[i].Type == ACT_PASSIVE) && PetActionBar[i].SpellOrAction == oldid) { PetActionBar[i].SpellOrAction = newid; if(!oldid) @@ -11333,188 +10854,9 @@ void CharmInfo::SetPetNumber(uint32 petnumber, bool statwindow) bool Unit::isFrozen() const { - AuraList const& mRoot = GetAurasByType(SPELL_AURA_MOD_ROOT); - for(AuraList::const_iterator i = mRoot.begin(); i != mRoot.end(); ++i) - if( GetSpellSchoolMask((*i)->GetSpellProto()) & SPELL_SCHOOL_MASK_FROST) - return true; - return false; + return HasAuraState(AURA_STATE_FROZEN); } -/* -struct ProcTriggeredData -{ - ProcTriggeredData(Aura* _triggeredByAura, uint32 _cooldown) - : triggeredByAura(_triggeredByAura), - triggeredByAura_SpellPair(Unit::spellEffectPair(triggeredByAura->GetId(),triggeredByAura->GetEffIndex())), - cooldown(_cooldown) - {} - - Aura* triggeredByAura; // triggred aura, can be invalidate at triggered aura proccessing - Unit::spellEffectPair triggeredByAura_SpellPair; // spell pair, used for re-find aura (by pointer comparison in range) - uint32 cooldown; // possible hidden cooldown -}; - -typedef std::list< ProcTriggeredData > ProcTriggeredList; - -void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, AuraTypeSet const& procAuraTypes, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage, SpellSchoolMask damageSchoolMask ) -{ - for(AuraTypeSet::const_iterator aur = procAuraTypes.begin(); aur != procAuraTypes.end(); ++aur) - { - // List of spells (effects) that proceed. Spell prototype and aura-specific value (damage for TRIGGER_DAMAGE) - ProcTriggeredList procTriggered; - - AuraList const& auras = GetAurasByType(*aur); - for(AuraList::const_iterator i = auras.begin(), next; i != auras.end(); i = next) - { - next = i; ++next; - - Aura* i_aura = *i; - - uint32 cooldown; // returned at next line - if(!IsTriggeredAtSpellProcEvent(i_aura->GetSpellProto(), procSpell, procFlag,attType,isVictim,cooldown)) - continue; - - procTriggered.push_back( ProcTriggeredData(i_aura, cooldown) ); - } - - // Handle effects proceed this time - for(ProcTriggeredList::iterator i = procTriggered.begin(); i != procTriggered.end(); ++i) - { - // Some auras can be deleted in function called in this loop (except first, ofc) - // Until storing auras in std::multimap to hard check deleting by another way - if(i != procTriggered.begin()) - { - bool found = false; - AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair); - AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair); - for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr) - { - if(itr->second==i->triggeredByAura) - { - found = true; - break; - } - } - - if(!found) - { - sLog.outError("Spell aura %u (id:%u effect:%u) has been deleted before call spell proc event handler",*aur,i->triggeredByAura_SpellPair.first,i->triggeredByAura_SpellPair.second); - sLog.outError("It can be deleted one from early processed auras:"); - for(ProcTriggeredList::iterator i2 = procTriggered.begin(); i != i2; ++i2) - sLog.outError(" Spell aura %u (id:%u effect:%u)",*aur,i2->triggeredByAura_SpellPair.first,i2->triggeredByAura_SpellPair.second); - sLog.outError(" <end of list>"); - continue; - } - } - - /// this is aura triggering code call - Aura* triggeredByAura = i->triggeredByAura; - - /// save charges existence before processing to prevent crash at access to deleted triggered aura after - /// used in speedup code check before check aura existance. - bool triggeredByAuraWithCharges = triggeredByAura->m_procCharges > 0; - - /// success in event proccesing - /// used in speedup code check before check aura existance. - bool casted = false; - - /// process triggered code - switch(*aur) - { - case SPELL_AURA_PROC_TRIGGER_SPELL: - { - sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s proc aura of spell %u)", - (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); - casted = HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, attType, i->cooldown); - break; - } - case SPELL_AURA_PROC_TRIGGER_DAMAGE: - { - uint32 triggered_damage = triggeredByAura->GetModifier()->m_amount; - sLog.outDebug("ProcDamageAndSpell: doing %u damage (triggered by %s aura of spell %u)", - triggered_damage, (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); - SpellNonMeleeDamageLog(pTarget, triggeredByAura->GetId(), triggered_damage, true, true); - casted = true; - break; - } - case SPELL_AURA_DUMMY: - { - uint32 effect = triggeredByAura->GetEffIndex(); - sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s dummy aura of spell %u)", - (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); - casted = HandleDummyAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag,i->cooldown); - break; - } - case SPELL_AURA_PRAYER_OF_MENDING: - { - sLog.outDebug("ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)", - (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); - - casted = HandleMeandingAuraProc(triggeredByAura); - break; - } - case SPELL_AURA_MOD_HASTE: - { - sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s haste aura of spell %u)", - (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); - casted = HandleHasteAuraProc(pTarget, damage, triggeredByAura, procSpell, procFlag,i->cooldown); - break; - } - case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: - { - // nothing do, just charges counter - // but count only in case appropriate school damage - casted = triggeredByAura->GetModifier()->m_miscvalue & damageSchoolMask; - break; - } - case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: - { - sLog.outDebug("ProcDamageAndSpell: casting spell (triggered by %s class script aura of spell %u)", - (isVictim?"a victim's":"an attacker's"),triggeredByAura->GetId()); - casted = HandleOverrideClassScriptAuraProc(pTarget, triggeredByAura, procSpell,i->cooldown); - break; - } - default: - { - // nothing do, just charges counter - casted = true; - break; - } - } - - /// Update charge (aura can be removed by triggers) - if(casted && triggeredByAuraWithCharges) - { - /// need re-found aura (can be dropped by triggers) - AuraMap::const_iterator lower = GetAuras().lower_bound(i->triggeredByAura_SpellPair); - AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair); - for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr) - { - if(itr->second == triggeredByAura) // pointer still valid - { - if(triggeredByAura->m_procCharges > 0) - triggeredByAura->m_procCharges -= 1; - - triggeredByAura->UpdateAuraCharges(); - break; - } - } - } - } - - /// Safely remove auras with zero charges - for(AuraList::const_iterator i = auras.begin(), next; i != auras.end(); i = next) - { - next = i; ++next; - if((*i)->m_procCharges == 0) - { - RemoveAurasDueToSpell((*i)->GetId()); - next = auras.begin(); - } - } - } -} -*/ struct ProcTriggeredData { ProcTriggeredData(SpellProcEventEntry const * _spellProcEvent, Aura* _triggeredByAura) @@ -11533,9 +10875,7 @@ typedef std::list< uint32> RemoveSpellList; // in most case need for drop charges // in some types of aura need do additional check // for example SPELL_AURA_MECHANIC_IMMUNITY - need check for mechanic -static bool isTriggerAura[TOTAL_AURAS]; -static bool isNonTriggerAura[TOTAL_AURAS]; -void InitTriggerAuraData() +bool InitTriggerAuraData() { for (int i=0;i<TOTAL_AURAS;i++) { @@ -11554,7 +10894,7 @@ void InitTriggerAuraData() isTriggerAura[SPELL_AURA_DAMAGE_IMMUNITY] = true; isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL] = true; isTriggerAura[SPELL_AURA_PROC_TRIGGER_DAMAGE] = true; - isTriggerAura[SPELL_AURA_MOD_CASTING_SPEED] = true; + isTriggerAura[SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK] = true; isTriggerAura[SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT] = true; isTriggerAura[SPELL_AURA_MOD_POWER_COST_SCHOOL] = true; isTriggerAura[SPELL_AURA_REFLECT_SPELLS_SCHOOL] = true; @@ -11569,9 +10909,13 @@ void InitTriggerAuraData() isTriggerAura[SPELL_AURA_MOD_HASTE] = true; isTriggerAura[SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE]=true; isTriggerAura[SPELL_AURA_PRAYER_OF_MENDING] = true; + isTriggerAura[SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE] = true; + isTriggerAura[SPELL_AURA_MOD_DAMAGE_FROM_CASTER] = true; isNonTriggerAura[SPELL_AURA_MOD_POWER_REGEN]=true; - isNonTriggerAura[SPELL_AURA_RESIST_PUSHBACK]=true; + isNonTriggerAura[SPELL_AURA_REDUCE_PUSHBACK]=true; + + return true; } uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition) @@ -11612,18 +10956,8 @@ uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missC return procEx; } -static int deep = 0; void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, SpellEntry const * procSpell, uint32 damage ) { - deep ++; - if (deep > 5) - { - sLog.outError("Prevent possible stack owerflow in Unit::ProcDamageAndSpellFor"); - if (procSpell) - sLog.outError(" Spell %u", procSpell->Id); - deep--; - return; - } // For melee/ranged based attack need update skills and set some Aura states if (procFlag & MELEE_BASED_TRIGGER_MASK) { @@ -11634,7 +10968,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag if (procExtra&(PROC_EX_NORMAL_HIT|PROC_EX_MISS|PROC_EX_RESIST)) { if (pTarget->GetTypeId() != TYPEID_PLAYER && pTarget->GetCreatureType() != CREATURE_TYPE_CRITTER) - ((Player*)this)->UpdateCombatSkills(pTarget, attType, MELEE_HIT_MISS, isVictim); + ((Player*)this)->UpdateCombatSkills(pTarget, attType, isVictim); } // Update defence if player is victim and parry/dodge/block if (isVictim && procExtra&(PROC_EX_DODGE|PROC_EX_PARRY|PROC_EX_BLOCK)) @@ -11686,17 +11020,6 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag ((Player*)this)->AddComboPoints(pTarget, 1); StartReactiveTimer( REACTIVE_OVERPOWER ); } - // Enable AURA_STATE_CRIT on crit - if (procExtra & PROC_EX_CRITICAL_HIT) - { - ModifyAuraState(AURA_STATE_CRIT, true); - StartReactiveTimer( REACTIVE_CRIT ); - if(getClass()==CLASS_HUNTER) - { - ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, true); - StartReactiveTimer( REACTIVE_HUNTER_CRIT ); - } - } } } } @@ -11707,11 +11030,16 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag for(AuraMap::const_iterator itr = GetAuras().begin(); itr!= GetAuras().end(); ++itr) { SpellProcEventEntry const* spellProcEvent = NULL; - if(!IsTriggeredAtSpellProcEvent(itr->second, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), spellProcEvent)) + if(!IsTriggeredAtSpellProcEvent(pTarget, itr->second, procSpell, procFlag, procExtra, attType, isVictim, (damage > 0), spellProcEvent)) continue; procTriggered.push_back( ProcTriggeredData(spellProcEvent, itr->second) ); } + + // Nothing found + if (procTriggered.empty()) + return; + // Handle effects proceed this time for(ProcTriggeredList::iterator i = procTriggered.begin(); i != procTriggered.end(); ++i) { @@ -11746,7 +11074,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag Modifier *auraModifier = triggeredByAura->GetModifier(); SpellEntry const *spellInfo = triggeredByAura->GetSpellProto(); uint32 effIndex = triggeredByAura->GetEffIndex(); - bool useCharges = triggeredByAura->m_procCharges > 0; + bool useCharges = triggeredByAura->GetAuraCharges() > 0; // For players set spell cooldown if need uint32 cooldown = 0; if (GetTypeId() == TYPEID_PLAYER && spellProcEvent && spellProcEvent->cooldown) @@ -11790,7 +11118,7 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: { sLog.outDebug("ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); - if (!HandleOverrideClassScriptAuraProc(pTarget, triggeredByAura, procSpell, cooldown)) + if (!HandleOverrideClassScriptAuraProc(pTarget, damage, triggeredByAura, procSpell, cooldown)) continue; break; } @@ -11802,23 +11130,15 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag HandleMeandingAuraProc(triggeredByAura); break; } - case SPELL_AURA_MOD_STUN: - // Remove by default, but if charge exist drop it - if (triggeredByAura->m_procCharges == 0) - removedSpells.push_back(triggeredByAura->GetId()); - break; - case SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS: - case SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS: - // Hunter's Mark (1-4 Rangs) - if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && (spellInfo->SpellFamilyFlags&0x0000000000000400LL)) - { - uint32 basevalue = triggeredByAura->GetBasePoints(); - auraModifier->m_amount += basevalue/10; - if (auraModifier->m_amount > basevalue*4) - auraModifier->m_amount = basevalue*4; - } + case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE: + { + sLog.outDebug("ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id,(isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); + + if (!HandleProcTriggerSpell(pTarget, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) + continue; break; - case SPELL_AURA_MOD_CASTING_SPEED: + } + case SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK: // Skip melee hits or instant cast spells if (procSpell == NULL || GetSpellCastTime(procSpell) == 0) continue; @@ -11846,6 +11166,11 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag if (procSpell==NULL || procSpell->Mechanic != auraModifier->m_miscvalue) continue; break; + case SPELL_AURA_MOD_DAMAGE_FROM_CASTER: + // Compare casters + if (triggeredByAura->GetCasterGUID() != pTarget->GetGUID()) + continue; + break; default: // nothing do, just charges counter break; @@ -11858,18 +11183,16 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag AuraMap::const_iterator upper = GetAuras().upper_bound(i->triggeredByAura_SpellPair); for(AuraMap::const_iterator itr = lower; itr!= upper; ++itr) { - if(itr->second == i->triggeredByAura) + // If last charge dropped add spell to remove list + if(itr->second == i->triggeredByAura && triggeredByAura->DropAuraCharge()) { - triggeredByAura->m_procCharges -=1; - triggeredByAura->UpdateAuraCharges(); - if (triggeredByAura->m_procCharges <= 0) - removedSpells.push_back(triggeredByAura->GetId()); + removedSpells.push_back(triggeredByAura->GetId()); break; } } } } - if (removedSpells.size()) + if (!removedSpells.empty()) { // Sort spells and remove dublicates removedSpells.sort(); @@ -11878,7 +11201,6 @@ void Unit::ProcDamageAndSpellFor( bool isVictim, Unit * pTarget, uint32 procFlag for(RemoveSpellList::const_iterator i = removedSpells.begin(); i != removedSpells.end();i++) RemoveAurasDueToSpell(*i); } - deep--; } SpellSchoolMask Unit::GetMeleeDamageSchoolMask() const @@ -11907,8 +11229,11 @@ void Unit::SendPetCastFail(uint32 spellid, uint8 msg) return; WorldPacket data(SMSG_PET_CAST_FAILED, (4+1)); + data << uint8(0); // cast count? data << uint32(spellid); data << uint8(msg); + // uint32 for some reason + // uint32 for some reason ((Player*)owner)->GetSession()->SendPacket(&data); } @@ -12068,15 +11393,16 @@ void Unit::SetConfused(bool apply, uint64 casterGUID, uint32 spellID) bool Unit::IsSitState() const { uint8 s = getStandState(); - return s == PLAYER_STATE_SIT_CHAIR || s == PLAYER_STATE_SIT_LOW_CHAIR || - s == PLAYER_STATE_SIT_MEDIUM_CHAIR || s == PLAYER_STATE_SIT_HIGH_CHAIR || - s == PLAYER_STATE_SIT; + return + s == UNIT_STAND_STATE_SIT_CHAIR || s == UNIT_STAND_STATE_SIT_LOW_CHAIR || + s == UNIT_STAND_STATE_SIT_MEDIUM_CHAIR || s == UNIT_STAND_STATE_SIT_HIGH_CHAIR || + s == UNIT_STAND_STATE_SIT; } bool Unit::IsStandState() const { uint8 s = getStandState(); - return !IsSitState() && s != PLAYER_STATE_SLEEP && s != PLAYER_STATE_KNEEL; + return !IsSitState() && s != UNIT_STAND_STATE_SLEEP && s != UNIT_STAND_STATE_KNEEL; } void Unit::SetStandState(uint8 state) @@ -12130,7 +11456,6 @@ void Unit::ClearComboPointHolders() void Unit::ClearAllReactives() { - for(int i=0; i < MAX_REACTIVE; ++i) m_reactiveTimer[i] = 0; @@ -12138,11 +11463,6 @@ void Unit::ClearAllReactives() ModifyAuraState(AURA_STATE_DEFENSE, false); if (getClass() == CLASS_HUNTER && HasAuraState( AURA_STATE_HUNTER_PARRY)) ModifyAuraState(AURA_STATE_HUNTER_PARRY, false); - if (HasAuraState( AURA_STATE_CRIT)) - ModifyAuraState(AURA_STATE_CRIT, false); - if (getClass() == CLASS_HUNTER && HasAuraState( AURA_STATE_HUNTER_CRIT_STRIKE) ) - ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, false); - if(getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER) ((Player*)this)->ClearComboPoints(); } @@ -12170,14 +11490,6 @@ void Unit::UpdateReactives( uint32 p_time ) if ( getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_PARRY)) ModifyAuraState(AURA_STATE_HUNTER_PARRY, false); break; - case REACTIVE_CRIT: - if (HasAuraState(AURA_STATE_CRIT)) - ModifyAuraState(AURA_STATE_CRIT, false); - break; - case REACTIVE_HUNTER_CRIT: - if ( getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_CRIT_STRIKE) ) - ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE, false); - break; case REACTIVE_OVERPOWER: if(getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER) ((Player*)this)->ClearComboPoints(); @@ -12197,7 +11509,7 @@ Unit* Unit::SelectNearbyTarget(float dist) const { std::list<Unit *> targets; Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(this, this, dist); - Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(targets, u_check); + Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(this, targets, u_check); VisitNearbyObject(dist, searcher); // remove current target @@ -12230,6 +11542,16 @@ Unit* Unit::SelectNearbyTarget(float dist) const return *tcIter; } +bool Unit::hasNegativeAuraWithInterruptFlag(uint32 flag) +{ + for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); ++iter) + { + if (!iter->second->IsPositive() && iter->second->GetSpellProto()->AuraInterruptFlags & flag) + return true; + } + return false; +} + void Unit::ApplyAttackTimePercentMod( WeaponAttackType att,float val, bool apply ) { float remainingTimePct = (float)m_attackTimer[att] / (GetAttackTime(att) * m_modAttackSpeedPct[att]); @@ -12291,6 +11613,8 @@ uint32 Unit::GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectT case SPELL_AURA_PERIODIC_LEECH: if ( GetSpellDuration(spellProto) ) overTime = GetSpellDuration(spellProto); + if (IsChanneledSpell(spellProto)) + ModSpellCastTime(spellProto, overTime); break; default: // -5% per additional effect @@ -12346,13 +11670,15 @@ uint32 Unit::GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectT void Unit::UpdateAuraForGroup(uint8 slot) { + if(slot >= MAX_AURAS) // slot not found, return + return; if(GetTypeId() == TYPEID_PLAYER) { Player* player = (Player*)this; if(player->GetGroup()) { player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_AURAS); - player->SetAuraUpdateMask(slot); + player->SetAuraUpdateMaskForRaid(slot); } } else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) @@ -12364,10 +11690,11 @@ void Unit::UpdateAuraForGroup(uint8 slot) if(owner && (owner->GetTypeId() == TYPEID_PLAYER) && ((Player*)owner)->GetGroup()) { ((Player*)owner)->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_AURAS); - pet->SetAuraUpdateMask(slot); + pet->SetAuraUpdateMaskForRaid(slot); } } } + SetAuraUpdateMask(slot); } float Unit::GetAPMultiplier(WeaponAttackType attType, bool normalized) @@ -12462,7 +11789,12 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction()); pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, spell_id); - if(!pet->InitStatsForLevel(creatureTarget->getLevel())) + if(GetTypeId()==TYPEID_PLAYER) + pet->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + + uint32 level = (creatureTarget->getLevel() < (getLevel() - 5)) ? (getLevel() - 5) : creatureTarget->getLevel(); + + if(!pet->InitStatsForLevel(level)) { sLog.outError("ERROR: Pet::InitStatsForLevel() failed for creature (Entry: %u)!",creatureTarget->GetEntry()); delete pet; @@ -12473,12 +11805,13 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) // this enables pet details window (Shift+P) pet->AIM_Initialize(); pet->InitPetCreateSpells(); + pet->InitTalentForLevel(); pet->SetHealth(pet->GetMaxHealth()); return pet; } -bool Unit::IsTriggeredAtSpellProcEvent(Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent ) +bool Unit::IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent ) { SpellEntry const* spellProto = aura->GetSpellProto (); @@ -12508,7 +11841,17 @@ bool Unit::IsTriggeredAtSpellProcEvent(Aura* aura, SpellEntry const* procSpell, if(!SpellMgr::IsSpellProcEventCanTriggeredBy(spellProcEvent, EventProcFlag, procSpell, procFlag, procExtra, active)) return false; - // Aura added by spell can`t trogger from self (prevent drop cahres/do triggers) + // In most cases req get honor or XP from kill + if (EventProcFlag & PROC_FLAG_KILL && GetTypeId() == TYPEID_PLAYER) + { + bool allow = ((Player*)this)->isHonorOrXPTarget(pVictim); + // Shadow Word: Death - can trigger from every kill + if (aura->GetId() == 32409) + allow = true; + if (!allow) + return false; + } + // Aura added by spell can`t trogger from self (prevent drop charges/do triggers) // But except periodic triggers (can triggered from self) if(procSpell && procSpell->Id == spellProto->Id && !(spellProto->procFlags&PROC_FLAG_ON_TAKE_PERIODIC)) return false; @@ -12520,13 +11863,13 @@ bool Unit::IsTriggeredAtSpellProcEvent(Aura* aura, SpellEntry const* procSpell, { Item *item = NULL; if(attType == BASE_ATTACK) - item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); else if (attType == OFF_ATTACK) - item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); else - item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED); + item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED); - if (!((Player*)this)->IsUseEquipedWeapon(attType==BASE_ATTACK)) + if (((Player*)this)->IsInFeralForm()) return false; if(!item || item->IsBroken() || item->GetProto()->Class != ITEM_CLASS_WEAPON || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) @@ -12535,7 +11878,7 @@ bool Unit::IsTriggeredAtSpellProcEvent(Aura* aura, SpellEntry const* procSpell, else if(spellProto->EquippedItemClass == ITEM_CLASS_ARMOR) { // Check if player is wearing shield - Item *item = ((Player*)this)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); + Item *item = ((Player*)this)->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); if(!item || item->IsBroken() || item->GetProto()->Class != ITEM_CLASS_ARMOR || !((1<<item->GetProto()->SubClass) & spellProto->EquippedItemSubClassMask)) return false; } @@ -12553,7 +11896,10 @@ bool Unit::IsTriggeredAtSpellProcEvent(Aura* aura, SpellEntry const* procSpell, } // Apply chance modifer aura if(Player* modOwner = GetSpellModOwner()) + { modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_CHANCE_OF_SUCCESS,chance); + modOwner->ApplySpellMod(spellProto->Id,SPELLMOD_PROC_CHANCE,chance); + } return roll_chance_f(chance); } @@ -12567,10 +11913,10 @@ bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura ) uint64 caster_guid = triggeredByAura->GetCasterGUID(); // jumps - int32 jumps = triggeredByAura->m_procCharges-1; + int32 jumps = triggeredByAura->GetAuraCharges()-1; // current aura expire - triggeredByAura->m_procCharges = 1; // will removed at next charges decrease + triggeredByAura->SetAuraCharges(1); // will removed at next charges decrease // next target selection if(jumps > 0 && GetTypeId()==TYPEID_PLAYER && IS_PLAYER_GUID(caster_guid)) @@ -12593,10 +11939,7 @@ bool Unit::HandleMeandingAuraProc( Aura* triggeredByAura ) mod->value = jumps-5; // negative mod->type = SPELLMOD_FLAT; mod->spellId = spellProto->Id; - mod->effectId = effIdx; - mod->lastAffected = NULL; - mod->mask = spellProto->SpellFamilyFlags; - mod->charges = 0; + mod->mask = spellProto->SpellFamilyFlags; caster->AddSpellMod(mod, true); CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID()); @@ -12654,7 +11997,7 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss) if(player && player!=pVictim) { if(player->RewardPlayerAndGroupAtKill(pVictim)) - player->ProcDamageAndSpell(pVictim, PROC_FLAG_KILL_AND_GET_XP, PROC_FLAG_KILLED, PROC_EX_NONE, 0); + player->ProcDamageAndSpell(pVictim, PROC_FLAG_KILL, PROC_FLAG_KILLED, PROC_EX_NONE, 0); else player->ProcDamageAndSpell(pVictim, PROC_FLAG_NONE, PROC_FLAG_KILLED,PROC_EX_NONE, 0); } @@ -12786,6 +12129,15 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss) bg->HandleKillUnit((Creature*)pVictim, player); } } + + // achievement stuff + if ( pVictim->GetTypeId() == TYPEID_PLAYER) + { + if(GetTypeId() == TYPEID_UNIT) + ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry()); + else if(GetTypeId() == TYPEID_PLAYER) + ((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1); + } } void Unit::SetControlled(bool apply, UnitState state) @@ -12855,7 +12207,7 @@ void Unit::SetStunned(bool apply) if(apply) { SetUInt64Value(UNIT_FIELD_TARGET, 0); - SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); CastStop(); // Creature specific @@ -12873,7 +12225,7 @@ void Unit::SetStunned(bool apply) { if(isAlive() && getVictim()) SetUInt64Value(UNIT_FIELD_TARGET, getVictim()->GetGUID()); - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); if(!hasUnitState(UNIT_STAT_ROOT)) // prevent allow move if have also root effect { @@ -13008,7 +12360,7 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess) { if(((Player*)this)->isAFK()) ((Player*)this)->ToggleAFK(); - ((Player*)this)->SetViewport(GetGUID(), false); + ((Player*)this)->SetClientControl(this, 0); } // Pets already have a properly initialized CharmInfo, don't overwrite it. @@ -13026,9 +12378,10 @@ void Unit::SetCharmedOrPossessedBy(Unit* charmer, bool possess) if(possess) { addUnitState(UNIT_STAT_POSSESSED); - SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); AddPlayerToVision((Player*)charmer); - ((Player*)charmer)->SetViewport(GetGUID(), true); + ((Player*)charmer)->SetClientControl(this, 1); + ((Player*)charmer)->SetMover(this); charmer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); } // Charm demon @@ -13077,7 +12430,7 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer) if(possess) { clearUnitState(UNIT_STAT_POSSESSED); - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_24); } if(GetTypeId() == TYPEID_UNIT) @@ -13098,7 +12451,7 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer) } } else - ((Player*)this)->SetViewport(GetGUID(), true); + ((Player*)this)->SetClientControl(this, 1); // If charmer still exists if(!charmer) @@ -13110,7 +12463,8 @@ void Unit::RemoveCharmedOrPossessedBy(Unit *charmer) if(possess) { RemovePlayerFromVision((Player*)charmer); - ((Player*)charmer)->SetViewport(charmer->GetGUID(), true); + ((Player*)charmer)->SetClientControl(charmer, 1); + ((Player*)charmer)->SetMover(charmer); charmer->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); } // restore UNIT_FIELD_BYTES_0 @@ -13251,6 +12605,55 @@ void Unit::GetPartyMember(std::list<Unit*> &TagUnitMap, float radius) } } +void Unit::SendAuraUpdate(uint8 slot) +{ + WorldPacket data(SMSG_AURA_UPDATE); + + Aura * ptr=NULL; + VisibleAuraMap const *visibleAuras = GetVisibleAuras(); + AuraSlotEntry * entry=GetVisibleAura(slot); + if (!entry) + return; + + //Get pointer to first aura-it doesn't matter which one we use (at least it shouldn't) + for (uint8 i=0 ; i<3; i++) + { + if (entry->m_slotAuras[i]) + { + ptr=entry->m_slotAuras[i]; + break; + } + } + + data.append(GetPackGUID()); + data << uint8(slot); + data << uint32(ptr ? ptr->GetId() : 0); + + if(!ptr) + { + RemoveVisibleAura(slot); + SendMessageToSet(&data, true); + return; + } + + data << uint8(entry->m_Flags); + data << uint8(entry->m_Level); + data << uint8(ptr->GetAuraCharges()? ptr->GetAuraCharges() : ptr->GetStackAmount()); + + if(!(entry->m_Flags & AFLAG_NOT_CASTER)) + { + data << uint8(0); // pguid + } + + if(entry->m_Flags & AFLAG_DURATION) + { + data << uint32(ptr->GetAuraMaxDuration()); + data << uint32(ptr->GetAuraDuration()); + } + + SendMessageToSet(&data, true); +} + void Unit::AddAura(uint32 spellId, Unit* target) { if(!target || !target->isAlive()) @@ -13267,7 +12670,7 @@ void Unit::AddAura(uint32 spellId, Unit* target) { if(spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA) { - if(target->IsImmunedToSpellEffect(spellInfo->Effect[i], spellInfo->EffectMechanic[i])) + if(target->IsImmunedToSpellEffect(spellInfo, i)) continue; /*if(spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_CASTER) @@ -13282,4 +12685,70 @@ void Unit::AddAura(uint32 spellId, Unit* target) } } } -}
\ No newline at end of file +} + +// Melee based spells can be miss, parry or dodge on this step +// Crit or block - determined on damage calculation phase! (and can be both in some time) +float Unit::MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const +{ + // Calculate hit chance (more correct for chance mod) + int32 HitChance; + + // PvP - PvE melee chances + /*int32 lchance = pVictim->GetTypeId() == TYPEID_PLAYER ? 5 : 7; + int32 leveldif = pVictim->getLevelForTarget(this) - getLevelForTarget(pVictim); + if(leveldif < 3) + HitChance = 95 - leveldif; + else + HitChance = 93 - (leveldif - 2) * lchance;*/ + if (spellId || attType == RANGED_ATTACK || !haveOffhandWeapon()) + HitChance = 95.0f; + else + HitChance = 76.0f; + + // Hit chance depends from victim auras + if(attType == RANGED_ATTACK) + HitChance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE); + else + HitChance += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE); + + // Spellmod from SPELLMOD_RESIST_MISS_CHANCE + if(spellId) + { + if(Player *modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_MISS_CHANCE, HitChance); + } + + // Miss = 100 - hit + float miss_chance= 100.0f - HitChance; + + // Bonuses from attacker aura and ratings + if (attType == RANGED_ATTACK) + miss_chance -= m_modRangedHitChance; + else + miss_chance -= m_modMeleeHitChance; + + // bonus from skills is 0.04% + //miss_chance -= skillDiff * 0.04f; + int32 diff = -skillDiff; + if(pVictim->GetTypeId()==TYPEID_PLAYER) + miss_chance += diff > 0 ? diff * 0.04 : diff * 0.02; + else + miss_chance += diff > 10 ? 2 + (diff - 10) * 0.4 : diff * 0.1; + + // Limit miss chance from 0 to 60% + if (miss_chance < 0.0f) + return 0.0f; + if (miss_chance > 60.0f) + return 60.0f; + return miss_chance; +} + +void Unit::SetPhaseMask(uint32 newPhaseMask, bool update) +{ + WorldObject::SetPhaseMask(newPhaseMask,update); + + if(IsInWorld()) + if(Pet* pet = GetPet()) + pet->SetPhaseMask(newPhaseMask,true); +} diff --git a/src/game/Unit.h b/src/game/Unit.h index 7050121c5bb..9ed85ca9cc3 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -45,7 +45,8 @@ enum SpellInterruptFlags SPELL_INTERRUPT_FLAG_PUSH_BACK = 0x02, // push back SPELL_INTERRUPT_FLAG_INTERRUPT = 0x04, // interrupt SPELL_INTERRUPT_FLAG_AUTOATTACK = 0x08, // no - SPELL_INTERRUPT_FLAG_DAMAGE = 0x10 // _complete_ interrupt on direct damage? + SPELL_INTERRUPT_FLAG_ABORT_ON_DMG = 0x10, // _complete_ interrupt on direct damage + //SPELL_INTERRUPT_UNK = 0x20 // unk, 564 of 727 spells having this spell start with "Glyph" }; enum SpellChannelInterruptFlags @@ -101,7 +102,7 @@ enum SpellModOp SPELLMOD_CASTING_TIME = 10, SPELLMOD_COOLDOWN = 11, SPELLMOD_EFFECT2 = 12, - // spellmod 13 unused + SPELLMOD_IGNORE_ARMOR = 13, SPELLMOD_COST = 14, SPELLMOD_CRIT_DAMAGE_BONUS = 15, SPELLMOD_RESIST_MISS_CHANCE = 16, @@ -109,13 +110,16 @@ enum SpellModOp SPELLMOD_CHANCE_OF_SUCCESS = 18, SPELLMOD_ACTIVATION_TIME = 19, SPELLMOD_EFFECT_PAST_FIRST = 20, - SPELLMOD_CASTING_TIME_OLD = 21, + SPELLMOD_GLOBAL_COOLDOWN = 21, //TODO: GCD is not checked by server currently SPELLMOD_DOT = 22, SPELLMOD_EFFECT3 = 23, SPELLMOD_SPELL_BONUS_DAMAGE = 24, - // spellmod 25, 26 unused + // spellmod 25 + SPELLMOD_PROC_CHANCE = 26, SPELLMOD_MULTIPLE_VALUE = 27, - SPELLMOD_RESIST_DISPEL_CHANCE = 28 + SPELLMOD_RESIST_DISPEL_CHANCE = 28, + SPELLMOD_CRIT_DAMAGE_BONUS_2 = 29, //one not used spell + SPELLMOD_SPELL_COST_REFUND_ON_FAIL = 30 }; #define MAX_SPELLMOD 32 @@ -129,6 +133,35 @@ enum SpellFacingFlags #define BASE_MAXDAMAGE 2.0f #define BASE_ATTACK_TIME 2000 +// byte value (UNIT_FIELD_BYTES_1,0) +enum UnitStandStateType +{ + UNIT_STAND_STATE_STAND = 0, + UNIT_STAND_STATE_SIT = 1, + UNIT_STAND_STATE_SIT_CHAIR = 2, + UNIT_STAND_STATE_SLEEP = 3, + UNIT_STAND_STATE_SIT_LOW_CHAIR = 4, + UNIT_STAND_STATE_SIT_MEDIUM_CHAIR = 5, + UNIT_STAND_STATE_SIT_HIGH_CHAIR = 6, + UNIT_STAND_STATE_DEAD = 7, + UNIT_STAND_STATE_KNEEL = 8 +}; + +// byte flag value (UNIT_FIELD_BYTES_1,2) +enum UnitStandFlags +{ + UNIT_STAND_FLAGS_CREEP = 0x02, + UNIT_STAND_FLAGS_ALL = 0xFF +}; + +// byte flags value (UNIT_FIELD_BYTES_1,3) +enum UnitBytes1_Flags +{ + UNIT_BYTE1_FLAG_ALWAYS_STAND = 0x01, + UNIT_BYTE1_FLAG_UNTRACKABLE = 0x04, + UNIT_BYTE1_FLAG_ALL = 0xFF +}; + // high byte (3 from 0..3) of UNIT_FIELD_BYTES_2 enum ShapeshiftForm { @@ -149,6 +182,7 @@ enum ShapeshiftForm FORM_BERSERKERSTANCE = 0x13, FORM_TEST = 0x14, FORM_ZOMBIE = 0x15, + FORM_METAMORPHOSIS = 0x16, FORM_FLIGHT_EPIC = 0x1B, FORM_SHADOW = 0x1C, FORM_FLIGHT = 0x1D, @@ -168,14 +202,14 @@ enum SheathState // byte (1 from 0..3) of UNIT_FIELD_BYTES_2 enum UnitBytes2_Flags { - UNIT_BYTE2_FLAG_UNK0 = 0x01, - UNIT_BYTE2_FLAG_UNK1 = 0x02, - UNIT_BYTE2_FLAG_UNK2 = 0x04, + UNIT_BYTE2_FLAG_PVP = 0x01, + UNIT_BYTE2_FLAG_UNK1 = 0x02, + UNIT_BYTE2_FLAG_FFA_PVP = 0x04, UNIT_BYTE2_FLAG_SANCTUARY = 0x08, - UNIT_BYTE2_FLAG_AURAS = 0x10, // show possitive auras as positive, and allow its dispel - UNIT_BYTE2_FLAG_UNK5 = 0x20, - UNIT_BYTE2_FLAG_UNK6 = 0x40, - UNIT_BYTE2_FLAG_UNK7 = 0x80 + UNIT_BYTE2_FLAG_UNK4 = 0x10, + UNIT_BYTE2_FLAG_UNK5 = 0x20, + UNIT_BYTE2_FLAG_UNK6 = 0x40, + UNIT_BYTE2_FLAG_UNK7 = 0x80 }; // byte (2 from 0..3) of UNIT_FIELD_BYTES_2 @@ -185,7 +219,7 @@ enum UnitRename UNIT_RENAME_ALLOWED = 0x03 }; -#define CREATURE_MAX_SPELLS 4 +#define CREATURE_MAX_SPELLS 8 enum Swing { @@ -213,16 +247,27 @@ enum HitInfo HITINFO_UNK1 = 0x00000001, // req correct packet structure HITINFO_NORMALSWING2 = 0x00000002, HITINFO_LEFTSWING = 0x00000004, + HITINFO_UNK2 = 0x00000008, HITINFO_MISS = 0x00000010, - HITINFO_ABSORB = 0x00000020, // plays absorb sound - HITINFO_RESIST = 0x00000040, // resisted at least some damage - HITINFO_CRITICALHIT = 0x00000080, - HITINFO_UNK2 = 0x00000100, // wotlk? - HITINFO_UNK3 = 0x00002000, // wotlk? - HITINFO_GLANCING = 0x00004000, - HITINFO_CRUSHING = 0x00008000, - HITINFO_NOACTION = 0x00010000, - HITINFO_SWINGNOHITSOUND = 0x00080000 + HITINFO_ABSORB = 0x00000020, // absorbed damage + HITINFO_ABSORB2 = 0x00000040, // absorbed damage + HITINFO_RESIST = 0x00000080, // resisted atleast some damage + HITINFO_RESIST2 = 0x00000100, // resisted atleast some damage + HITINFO_CRITICALHIT = 0x00000200, // critical hit + // 0x00000400 + // 0x00000800 + // 0x00001000 + HITINFO_BLOCK = 0x00002000, // blocked damage + // 0x00004000 + // 0x00008000 + HITINFO_GLANCING = 0x00010000, + HITINFO_CRUSHING = 0x00020000, + HITINFO_NOACTION = 0x00040000, // guessed + // 0x00080000 + // 0x00100000 + HITINFO_SWINGNOHITSOUND = 0x00200000, // guessed + // 0x00400000 + HITINFO_UNK3 = 0x00800000 }; //i would like to remove this: (it is defined in item.h @@ -294,11 +339,13 @@ enum UnitMods UNIT_MOD_STAT_INTELLECT, UNIT_MOD_STAT_SPIRIT, UNIT_MOD_HEALTH, - UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_HAPPINESS must be in existed order, it's accessed by index values of Powers enum. + UNIT_MOD_MANA, // UNIT_MOD_MANA..UNIT_MOD_RUNIC_POWER must be in existed order, it's accessed by index values of Powers enum. UNIT_MOD_RAGE, UNIT_MOD_FOCUS, UNIT_MOD_ENERGY, UNIT_MOD_HAPPINESS, + UNIT_MOD_RUNE, + UNIT_MOD_RUNIC_POWER, UNIT_MOD_ARMOR, // UNIT_MOD_ARMOR..UNIT_MOD_RESISTANCE_ARCANE must be in existed order, it's accessed by index values of SpellSchools enum. UNIT_MOD_RESISTANCE_HOLY, UNIT_MOD_RESISTANCE_FIRE, @@ -318,7 +365,7 @@ enum UnitMods UNIT_MOD_RESISTANCE_START = UNIT_MOD_ARMOR, UNIT_MOD_RESISTANCE_END = UNIT_MOD_RESISTANCE_ARCANE + 1, UNIT_MOD_POWER_START = UNIT_MOD_MANA, - UNIT_MOD_POWER_END = UNIT_MOD_HAPPINESS + 1 + UNIT_MOD_POWER_END = UNIT_MOD_RUNIC_POWER + 1 }; enum BaseModGroup @@ -385,9 +432,10 @@ enum UnitMoveType MOVE_TURN_RATE = 5, MOVE_FLIGHT = 6, MOVE_FLIGHT_BACK = 7, + MOVE_PITCH_RATE = 8 }; -#define MAX_MOVE_TYPE 8 +#define MAX_MOVE_TYPE 9 extern float baseMoveSpeed[MAX_MOVE_TYPE]; // assume it is 25 yard per 0.6 second @@ -397,11 +445,10 @@ enum WeaponAttackType { BASE_ATTACK = 0, OFF_ATTACK = 1, - RANGED_ATTACK = 2 + RANGED_ATTACK = 2, + MAX_ATTACK }; -#define MAX_ATTACK 3 - enum CombatRating { CR_WEAPON_SKILL = 0, @@ -427,10 +474,11 @@ enum CombatRating CR_WEAPON_SKILL_MAINHAND = 20, CR_WEAPON_SKILL_OFFHAND = 21, CR_WEAPON_SKILL_RANGED = 22, - CR_EXPERTISE = 23 + CR_EXPERTISE = 23, + CR_ARMOR_PENETRATION = 24 }; -#define MAX_COMBAT_RATING 24 +#define MAX_COMBAT_RATING 25 enum DamageEffectType { @@ -455,45 +503,50 @@ enum UnitVisibility // Value masks for UNIT_FIELD_FLAGS enum UnitFlags { - UNIT_FLAG_UNKNOWN7 = 0x00000001, + UNIT_FLAG_UNK_0 = 0x00000001, UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable UNIT_FLAG_DISABLE_MOVE = 0x00000004, UNIT_FLAG_PVP_ATTACKABLE = 0x00000008, // allow apply pvp rules to attackable state in addition to faction dependent state UNIT_FLAG_RENAME = 0x00000010, UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP - UNIT_FLAG_UNKNOWN9 = 0x00000040, + UNIT_FLAG_UNK_6 = 0x00000040, UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080, // ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE UNIT_FLAG_NOT_ATTACKABLE_2 = 0x00000100, // 2.0.8 - UNIT_FLAG_UNKNOWN11 = 0x00000200, + UNIT_FLAG_UNK_9 = 0x00000200, // 3.0.3 - makes you unable to attack everything UNIT_FLAG_LOOTING = 0x00000400, // loot animation UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8 - UNIT_FLAG_PVP = 0x00001000, + UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3 UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1 - UNIT_FLAG_UNKNOWN4 = 0x00004000, // 2.0.8 - UNIT_FLAG_UNKNOWN13 = 0x00008000, - UNIT_FLAG_UNKNOWN14 = 0x00010000, - UNIT_FLAG_PACIFIED = 0x00020000, - UNIT_FLAG_DISABLE_ROTATE = 0x00040000, // stunned, 2.1.1 + UNIT_FLAG_UNK_14 = 0x00004000, // 2.0.8 + UNIT_FLAG_UNK_15 = 0x00008000, + UNIT_FLAG_UNK_16 = 0x00010000, + UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok + UNIT_FLAG_STUNNED = 0x00040000, // 3.0.3 ok UNIT_FLAG_IN_COMBAT = 0x00080000, UNIT_FLAG_TAXI_FLIGHT = 0x00100000, // disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag - UNIT_FLAG_DISARMED = 0x00200000, // disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. + UNIT_FLAG_DISARMED = 0x00200000, // 3.0.3, disable melee spells casting..., "Required melee weapon" added to melee spells tooltip. UNIT_FLAG_CONFUSED = 0x00400000, UNIT_FLAG_FLEEING = 0x00800000, - UNIT_FLAG_UNKNOWN5 = 0x01000000, // used in spell Eyes of the Beast for pet... + UNIT_FLAG_UNK_24 = 0x01000000, // used in spell Eyes of the Beast for pet... UNIT_FLAG_NOT_SELECTABLE = 0x02000000, UNIT_FLAG_SKINNABLE = 0x04000000, UNIT_FLAG_MOUNT = 0x08000000, - UNIT_FLAG_UNKNOWN17 = 0x10000000, - UNIT_FLAG_UNKNOWN6 = 0x20000000, // used in Feing Death spell - UNIT_FLAG_SHEATHE = 0x40000000 + UNIT_FLAG_UNK_28 = 0x10000000, + UNIT_FLAG_UNK_29 = 0x20000000, // used in Feing Death spell + UNIT_FLAG_SHEATHE = 0x40000000, + UNIT_FLAG_UNK_31 = 0x80000000 }; // Value masks for UNIT_FIELD_FLAGS_2 enum UnitFlags2 { - UNIT_FLAG2_FEIGN_DEATH = 0x00000001, - UNIT_FLAG2_COMPREHEND_LANG= 0x00000008, - UNIT_FLAG2_FORCE_MOVE = 0x00000040 + UNIT_FLAG2_FEIGN_DEATH = 0x00000001, + UNIT_FLAG2_UNK1 = 0x00000002, // Hide unit model (show only player equip) + UNIT_FLAG2_COMPREHEND_LANG = 0x00000008, + UNIT_FLAG2_FORCE_MOVE = 0x00000040, + UNIT_FLAG2_DISARM_OFFHAND = 0x00000080, + UNIT_FLAG2_DISARM_RANGED = 0x00000400, //this does not disable ranged weapon display (maybe additional flag needed?) + UNIT_FLAG2_REGENERATE_POWER = 0x00000800 }; /// Non Player Character flags @@ -581,8 +634,9 @@ struct DiminishingReturn enum MeleeHitOutcome { MELEE_HIT_EVADE, MELEE_HIT_MISS, MELEE_HIT_DODGE, MELEE_HIT_BLOCK, MELEE_HIT_PARRY, - MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL, MELEE_HIT_BLOCK_CRIT + MELEE_HIT_GLANCING, MELEE_HIT_CRIT, MELEE_HIT_CRUSHING, MELEE_HIT_NORMAL }; + struct CleanDamage { CleanDamage(uint32 _damage, WeaponAttackType _attackType, MeleeHitOutcome _hitOutCome) : @@ -639,8 +693,20 @@ uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missC struct UnitActionBarEntry { - uint32 Type; - uint32 SpellOrAction; + UnitActionBarEntry() : Raw(0) {} + + union + { + struct + { + uint16 SpellOrAction; + uint16 Type; + }; + struct + { + uint32 Raw; + }; + }; }; #define MAX_DECLINED_NAME_CASES 5 @@ -662,13 +728,12 @@ enum CurrentSpellTypes enum ActiveStates { - ACT_ENABLED = 0xC100, - ACT_DISABLED = 0x8100, - ACT_COMMAND = 0x0700, - ACT_REACTION = 0x0600, - ACT_CAST = 0x0100, - ACT_PASSIVE = 0x0000, - ACT_DECIDE = 0x0001 + ACT_PASSIVE = 0x0100, // 0x0100 - passive + ACT_DISABLED = 0x8100, // 0x8000 - castable + ACT_ENABLED = 0xC100, // 0x4000 | 0x8000 - auto cast + castable + ACT_COMMAND = 0x0700, // 0x0100 | 0x0200 | 0x0400 + ACT_REACTION = 0x0600, // 0x0200 | 0x0400 + ACT_DECIDE = 0x0001 // what is it? }; enum ReactStates @@ -733,16 +798,22 @@ struct TRINITY_DLL_SPEC CharmInfo enum ReactiveType { - REACTIVE_DEFENSE = 1, - REACTIVE_HUNTER_PARRY = 2, - REACTIVE_CRIT = 3, - REACTIVE_HUNTER_CRIT = 4, - REACTIVE_OVERPOWER = 5 + REACTIVE_DEFENSE = 0, + REACTIVE_HUNTER_PARRY = 1, + REACTIVE_OVERPOWER = 2 }; -#define MAX_REACTIVE 6 +#define MAX_REACTIVE 3 #define MAX_TOTEM 4 +struct AuraSlotEntry +{ + uint8 m_Flags; + uint8 m_Level; + uint32 m_spellId; + Aura * m_slotAuras[3]; +}; + // delay time next attack to prevent client attack animation problems #define ATTACK_DISPLAY_DELAY 200 @@ -756,9 +827,10 @@ class TRINITY_DLL_SPEC Unit : public WorldObject typedef std::multimap< spellEffectPair, Aura*> AuraMap; typedef std::list<Aura *> AuraList; typedef std::list<DiminishingReturn> Diminishing; - typedef std::set<AuraType> AuraTypeSet; typedef std::set<uint32> ComboPointHolderSet; + typedef std::map<uint8, AuraSlotEntry> VisibleAuraMap; + virtual ~Unit ( ); void AddToWorld(); @@ -797,9 +869,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject } void _removeAttacker(Unit *pAttacker) // must be called only from Unit::AttackStop() { - AttackerSet::iterator itr = m_attackers.find(pAttacker); - if(itr != m_attackers.end()) - m_attackers.erase(itr); + m_attackers.erase(pAttacker); } Unit * getAttackerForHelper() // If someone wants to help, who to give them { @@ -821,6 +891,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void CombatStop(bool cast = false); void CombatStopWithPets(bool cast = false); Unit* SelectNearbyTarget(float dist = NOMINAL_MELEE_RANGE) const; + bool hasNegativeAuraWithInterruptFlag(uint32 flag); void addUnitState(uint32 f) { m_state |= f; } bool hasUnitState(const uint32 f) const { return (m_state & f); } @@ -888,8 +959,14 @@ class TRINITY_DLL_SPEC Unit : public WorldObject return false; } - bool IsPvP() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); } - void SetPvP(bool state) { if(state) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); else RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); } + bool IsPvP() const { return HasByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); } + void SetPvP(bool state) + { + if(state) + SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); + else + RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP); + } uint32 GetCreatureType() const; uint32 GetCreatureTypeMask() const { @@ -902,6 +979,9 @@ class TRINITY_DLL_SPEC Unit : public WorldObject bool IsStandState() const; void SetStandState(uint8 state); + void SetStandFlags(uint8 flags) { SetByteFlag(UNIT_FIELD_BYTES_1, 2,flags); } + void RemoveStandFlags(uint8 flags) { RemoveByteFlag(UNIT_FIELD_BYTES_1, 2,flags); } + bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); } uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); } void Mount(uint32 mount); @@ -924,6 +1004,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss); void CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType = BASE_ATTACK); + int32 GetIgnoredArmorMultiplier(SpellEntry const *spellInfo, WeaponAttackType attackType); void DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss); float MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType, int32 skillDiff, uint32 spellId) const; @@ -935,6 +1016,16 @@ class TRINITY_DLL_SPEC Unit : public WorldObject float GetUnitParryChance() const; float GetUnitBlockChance() const; float GetUnitCriticalChance(WeaponAttackType attackType, const Unit *pVictim) const; + bool CanUseAttackType( uint8 attacktype ) const + { + switch(attacktype) + { + case BASE_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISARMED); + case OFF_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS_2,UNIT_FLAG2_DISARM_OFFHAND); + case RANGED_ATTACK: return !HasFlag(UNIT_FIELD_FLAGS_2,UNIT_FLAG2_DISARM_RANGED); + } + return true; + } virtual uint32 GetShieldBlockValue() const =0; uint32 GetUnitMeleeSkill(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } @@ -944,7 +1035,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject float GetPPMProcChance(uint32 WeaponSpeed, float PPM) const; MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType) const; - MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance, bool SpellCasted ) const; + MeleeHitOutcome RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const; bool isVendor() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR ); } bool isTrainer() const { return HasFlag( UNIT_NPC_FLAGS, UNIT_NPC_FLAG_TRAINER ); } @@ -984,7 +1075,10 @@ class TRINITY_DLL_SPEC Unit : public WorldObject bool HasAuraType(AuraType auraType) const; bool HasAura(uint32 spellId, uint32 effIndex) const - { return m_Auras.find(spellEffectPair(spellId, effIndex)) != m_Auras.end(); } + { + return m_Auras.find(spellEffectPair(spellId, effIndex)) != m_Auras.end(); + } + bool HasAura(uint32 spellId) const; bool virtual HasSpell(uint32 /*spellID*/) const { return false; } @@ -1104,11 +1198,11 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT); void RemoveAura(uint32 spellId, uint32 effindex, Aura* except = NULL); - void RemoveSingleAuraFromStackByDispel(uint32 spellId); + void RemoveSingleSpellAurasFromStack(uint32 spellId); void RemoveSingleAuraFromStack(uint32 spellId, uint32 effindex); void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL); void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId); - void RemoveAurasDueToCasterSpell(uint32 spellId, uint64 guid); + void RemoveAurasByCasterSpell(uint32 spellId, uint64 casterGUID); void RemoveAurasDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler); void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer); void RemoveAurasDueToSpellByCancel(uint32 spellId); @@ -1224,13 +1318,13 @@ class TRINITY_DLL_SPEC Unit : public WorldObject bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false, bool is3dDistance = true) const; bool canDetectInvisibilityOf(Unit const* u) const; bool canDetectStealthOf(Unit const* u, float distance) const; + void SetPhaseMask(uint32 newPhaseMask, bool update);// overwrite WorldObject::SetPhaseMask // virtual functions for all world objects types bool isVisibleForInState(Player const* u, bool inVisibleList) const; // function for low level grid visibility checks in player/creature cases virtual bool IsVisibleInGridForPlayer(Player const* pl) const = 0; - bool waterbreath; AuraList & GetSingleCastAuras() { return m_scAuras; } AuraList const& GetSingleCastAuras() const { return m_scAuras; } SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; @@ -1247,12 +1341,32 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void removeHatedBy(HostilReference* /*pHostilReference*/ ) { /* nothing to do yet */ } HostilRefManager& getHostilRefManager() { return m_HostilRefManager; } + VisibleAuraMap const *GetVisibleAuras() { return &m_visibleAuras; } + uint8 GetVisibleAurasCount() { return m_visibleAuras.size(); } + AuraSlotEntry * GetVisibleAura(uint8 slot) + { + VisibleAuraMap::iterator itr = m_visibleAuras.find(slot); + if(itr != m_visibleAuras.end()) + return &itr->second; + return 0; + } + void SetVisibleAura(uint8 slot, AuraSlotEntry entry) { m_visibleAuras[slot] = entry; } + void RemoveVisibleAura(uint8 slot) { m_visibleAuras.erase(slot); } + + const uint64& GetAuraUpdateMask() const { return m_auraUpdateMask; } + void SetAuraUpdateMask(uint8 slot) { m_auraUpdateMask |= (uint64(1) << slot); } + void ResetAuraUpdateMask() { m_auraUpdateMask = 0; } + void SendAuraUpdate(uint8 slot); + Aura* GetAura(uint32 spellId, uint32 effindex); + Aura* GetAura(AuraType type, uint32 family, uint32 familyFlag1 = 0, uint32 familyFlag2 = 0, uint32 familyFlag3 = 0, uint64 casterGUID = 0); + AuraMap & GetAuras() { return m_Auras; } AuraMap const& GetAuras() const { return m_Auras; } AuraList const& GetAurasByType(AuraType type) const { return m_modAuras[type]; } void ApplyAuraProcTriggerDamage(Aura* aura, bool apply); + bool HasAuraTypeWithMiscvalue(AuraType auratype, uint32 miscvalue) const; int32 GetTotalAuraModifier(AuraType auratype) const; float GetTotalAuraMultiplier(AuraType auratype) const; int32 GetMaxPositiveAuraModifier(AuraType auratype) const; @@ -1298,11 +1412,13 @@ class TRINITY_DLL_SPEC Unit : public WorldObject int32 SpellBaseHealingBonus(SpellSchoolMask schoolMask); int32 SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim); int32 SpellBaseHealingBonusForVictim(SpellSchoolMask schoolMask, Unit *pVictim); - uint32 SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 damage, DamageEffectType damagetype); - uint32 SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, Unit *pVictim); + uint32 SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 damage, DamageEffectType damagetype, uint32 stack = 1); + uint32 SpellHealingBonus(Unit *pVictim, SpellEntry const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1); bool isSpellBlocked(Unit *pVictim, SpellEntry const *spellProto, WeaponAttackType attackType = BASE_ATTACK); + bool isBlockCritical(); bool isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType = BASE_ATTACK); - uint32 SpellCriticalBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim); + uint32 SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim); + uint32 SpellCriticalHealingBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim); void SetLastManaUse(uint32 spellCastTime) { m_lastManaUse = spellCastTime; } bool IsUnderLastManaUseEffect() const; @@ -1314,14 +1430,14 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply); void ApplySpellDispelImmunity(const SpellEntry * spellProto, DispelType type, bool apply); - virtual bool IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges = false); + virtual bool IsImmunedToSpell(SpellEntry const* spellInfo); // redefined in Creature - bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask, bool useCharges = false); - virtual bool IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const; + bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask); + virtual bool IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const; // redefined in Creature - uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage); - void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist); + uint32 CalcArmorReducedDamage(Unit* pVictim, const uint32 damage, SpellEntry const *spellInfo, WeaponAttackType attackType=MAX_ATTACK); + void CalcAbsorbResist(Unit *pVictim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist, SpellEntry const *spellInfo = NULL); void UpdateSpeed(UnitMoveType mtype, bool forced); float GetSpeed( UnitMoveType mtype ) const; @@ -1335,7 +1451,9 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void _ApplyAllAuraMods(); int32 CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_index, int32 basePoints, Unit const* target); - int32 CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_index, Unit const* target); + int32 CalcSpellDuration(SpellEntry const* spellProto); + int32 ModSpellDuration(SpellEntry const* spellProto, uint8 effect_index, Unit const* target, int32 duration); + void ModSpellCastTime(SpellEntry const* spellProto, int32 & castTime); float CalculateLevelPenalty(SpellEntry const* spellProto) const; void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); } @@ -1418,6 +1536,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject DeathState m_deathState; + uint64 m_auraUpdateMask; AuraMap m_Auras; typedef std::list<uint64> DynObjectGUIDs; @@ -1438,6 +1557,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject float m_weaponDamage[MAX_ATTACK][2]; bool m_canModifyStats; //std::list< spellEffectPair > AuraSpells[TOTAL_AURAS]; // TODO: use this if ok for mem + VisibleAuraMap m_visibleAuras; float m_speed_rate[MAX_MOVE_TYPE]; @@ -1450,6 +1570,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject uint32 m_unit_movement_flags; uint32 m_reactiveTimer[MAX_REACTIVE]; + uint32 m_regenTimer; ThreatManager m_ThreatManager; @@ -1458,11 +1579,11 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void SendAttackStop(Unit* victim); // only from AttackStop(Unit*) //void SendAttackStart(Unit* pVictim); // only from Unit::AttackStart(Unit*) - bool IsTriggeredAtSpellProcEvent( Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent ); + bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent ); bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); bool HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); - bool HandleOverrideClassScriptAuraProc(Unit *pVictim, Aura* triggredByAura, SpellEntry const *procSpell, uint32 cooldown); + bool HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 cooldown); bool HandleMeandingAuraProc(Aura* triggeredByAura); uint32 m_state; // Even derived shouldn't modify diff --git a/src/game/UnitEvents.h b/src/game/UnitEvents.h index 35003c3d09e..0bde9ca5ada 100644 --- a/src/game/UnitEvents.h +++ b/src/game/UnitEvents.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/UpdateData.cpp b/src/game/UpdateData.cpp index 2b6282997e8..bdd3345751d 100644 --- a/src/game/UpdateData.cpp +++ b/src/game/UpdateData.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -108,7 +108,7 @@ bool UpdateData::BuildPacket(WorldPacket *packet, bool hasTransport) ByteBuffer buf(m_data.size() + 10 + m_outOfRangeGUIDs.size()*8); buf << (uint32) (!m_outOfRangeGUIDs.empty() ? m_blockCount + 1 : m_blockCount); - buf << (uint8) (hasTransport ? 1 : 0); + //buf << (uint8) (hasTransport ? 1 : 0); if(!m_outOfRangeGUIDs.empty()) { diff --git a/src/game/UpdateData.h b/src/game/UpdateData.h index 8fdcac4b400..c33e06589c1 100644 --- a/src/game/UpdateData.h +++ b/src/game/UpdateData.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,11 +38,12 @@ enum OBJECT_UPDATE_FLAGS UPDATEFLAG_NONE = 0x00, UPDATEFLAG_SELF = 0x01, UPDATEFLAG_TRANSPORT = 0x02, - UPDATEFLAG_FULLGUID = 0x04, + UPDATEFLAG_HAS_TARGET = 0x04, UPDATEFLAG_LOWGUID = 0x08, UPDATEFLAG_HIGHGUID = 0x10, UPDATEFLAG_LIVING = 0x20, - UPDATEFLAG_HASPOSITION = 0x40 + UPDATEFLAG_HAS_POSITION = 0x40, + UPDATEFLAG_VEHICLE = 0x80 }; class UpdateData diff --git a/src/game/UpdateFields.h b/src/game/UpdateFields.h index db64e0bc1dd..ca971dac460 100644 --- a/src/game/UpdateFields.h +++ b/src/game/UpdateFields.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ #ifndef _UPDATEFIELDS_AUTO_H #define _UPDATEFIELDS_AUTO_H -// Auto generated for version 2, 4, 3, 8606 +// Auto generated for version 3, 0, 3, 9183 enum EObjectFields { @@ -43,13 +43,37 @@ enum EItemFields ITEM_FIELD_DURATION = OBJECT_END + 0x0009, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 ITEM_FIELD_SPELL_CHARGES = OBJECT_END + 0x000A, // Size: 5, Type: INT, Flags: OWNER_ONLY, UNK2 ITEM_FIELD_FLAGS = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC - ITEM_FIELD_ENCHANTMENT = OBJECT_END + 0x0010, // Size: 33, Type: INT, Flags: PUBLIC - ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0031, // Size: 1, Type: INT, Flags: PUBLIC - ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0032, // Size: 1, Type: INT, Flags: PUBLIC - ITEM_FIELD_ITEM_TEXT_ID = OBJECT_END + 0x0033, // Size: 1, Type: INT, Flags: OWNER_ONLY - ITEM_FIELD_DURABILITY = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 - ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 - ITEM_END = OBJECT_END + 0x0036, + ITEM_FIELD_ENCHANTMENT_1_1 = OBJECT_END + 0x0010, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_1_3 = OBJECT_END + 0x0012, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_2_1 = OBJECT_END + 0x0013, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_2_3 = OBJECT_END + 0x0015, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_3_1 = OBJECT_END + 0x0016, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_3_3 = OBJECT_END + 0x0018, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_4_1 = OBJECT_END + 0x0019, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_4_3 = OBJECT_END + 0x001B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_5_1 = OBJECT_END + 0x001C, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_5_3 = OBJECT_END + 0x001E, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_6_1 = OBJECT_END + 0x001F, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_6_3 = OBJECT_END + 0x0021, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_7_1 = OBJECT_END + 0x0022, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_7_3 = OBJECT_END + 0x0024, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_8_1 = OBJECT_END + 0x0025, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_8_3 = OBJECT_END + 0x0027, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_9_1 = OBJECT_END + 0x0028, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_9_3 = OBJECT_END + 0x002A, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_10_1 = OBJECT_END + 0x002B, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_10_3 = OBJECT_END + 0x002D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_11_1 = OBJECT_END + 0x002E, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_11_3 = OBJECT_END + 0x0030, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_12_1 = OBJECT_END + 0x0031, // Size: 2, Type: INT, Flags: PUBLIC + ITEM_FIELD_ENCHANTMENT_12_3 = OBJECT_END + 0x0033, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + ITEM_FIELD_PROPERTY_SEED = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC + ITEM_FIELD_RANDOM_PROPERTIES_ID = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC + ITEM_FIELD_ITEM_TEXT_ID = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: OWNER_ONLY + ITEM_FIELD_DURABILITY = OBJECT_END + 0x0037, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 + ITEM_FIELD_MAXDURABILITY = OBJECT_END + 0x0038, // Size: 1, Type: INT, Flags: OWNER_ONLY, UNK2 + ITEM_FIELD_PAD = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: NONE + ITEM_END = OBJECT_END + 0x003A, }; enum EContainerFields @@ -64,93 +88,94 @@ enum EUnitFields { UNIT_FIELD_CHARM = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC UNIT_FIELD_SUMMON = OBJECT_END + 0x0002, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_CREATEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_TARGET = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_PERSUADED = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_CRITTER = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PRIVATE + UNIT_FIELD_CHARMEDBY = OBJECT_END + 0x0006, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_SUMMONEDBY = OBJECT_END + 0x0008, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_CREATEDBY = OBJECT_END + 0x000A, // Size: 2, Type: LONG, Flags: PUBLIC + UNIT_FIELD_TARGET = OBJECT_END + 0x000C, // Size: 2, Type: LONG, Flags: PUBLIC UNIT_FIELD_CHANNEL_OBJECT = OBJECT_END + 0x000E, // Size: 2, Type: LONG, Flags: PUBLIC - UNIT_FIELD_HEALTH = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: DYNAMIC - UNIT_FIELD_POWER1 = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER2 = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER3 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER4 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_POWER5 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: DYNAMIC - UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_LEVEL = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_BYTES_0 = OBJECT_END + 0x001E, // Size: 1, Type: BYTES, Flags: PUBLIC - UNIT_VIRTUAL_ITEM_SLOT_DISPLAY = OBJECT_END + 0x001F, // Size: 3, Type: INT, Flags: PUBLIC - UNIT_VIRTUAL_ITEM_INFO = OBJECT_END + 0x0022, // Size: 6, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_FLAGS = OBJECT_END + 0x0028, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0029, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_AURA = OBJECT_END + 0x002A, // Size: 56, Type: INT, Flags: PUBLIC - UNIT_FIELD_AURAFLAGS = OBJECT_END + 0x0062, // Size: 14, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_AURALEVELS = OBJECT_END + 0x0070, // Size: 14, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_AURAAPPLICATIONS = OBJECT_END + 0x007E, // Size: 14, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_AURASTATE = OBJECT_END + 0x008C, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x008D, // Size: 2, Type: INT, Flags: PUBLIC - UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x008F, // Size: 1, Type: INT, Flags: PRIVATE - UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x0090, // Size: 1, Type: FLOAT, Flags: PUBLIC - UNIT_FIELD_COMBATREACH = OBJECT_END + 0x0091, // Size: 1, Type: FLOAT, Flags: PUBLIC - UNIT_FIELD_DISPLAYID = OBJECT_END + 0x0092, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x0093, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x0094, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x0095, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 - UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0096, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 - UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0097, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 - UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0098, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 - UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0099, // Size: 1, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_PETNUMBER = OBJECT_END + 0x009A, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x009B, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x009C, // Size: 1, Type: INT, Flags: OWNER_ONLY - UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x009D, // Size: 1, Type: INT, Flags: OWNER_ONLY - UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x009E, // Size: 1, Type: INT, Flags: DYNAMIC - UNIT_CHANNEL_SPELL = OBJECT_END + 0x009F, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_MOD_CAST_SPEED = OBJECT_END + 0x00A0, // Size: 1, Type: FLOAT, Flags: PUBLIC - UNIT_CREATED_BY_SPELL = OBJECT_END + 0x00A1, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_NPC_FLAGS = OBJECT_END + 0x00A2, // Size: 1, Type: INT, Flags: DYNAMIC - UNIT_NPC_EMOTESTATE = OBJECT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_TRAINING_POINTS = OBJECT_END + 0x00A4, // Size: 1, Type: TWO_SHORT, Flags: OWNER_ONLY - UNIT_FIELD_STAT0 = OBJECT_END + 0x00A5, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_STAT1 = OBJECT_END + 0x00A6, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_STAT2 = OBJECT_END + 0x00A7, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_STAT3 = OBJECT_END + 0x00A8, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_STAT4 = OBJECT_END + 0x00A9, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x00AA, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x00AB, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x00AC, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x00AD, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x00AE, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x00AF, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x00B0, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x00B1, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x00B2, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x00B3, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_RESISTANCES = OBJECT_END + 0x00B4, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3 - UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x00BB, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x00C2, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_BASE_MANA = OBJECT_END + 0x00C9, // Size: 1, Type: INT, Flags: PUBLIC - UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x00CA, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_BYTES_2 = OBJECT_END + 0x00CB, // Size: 1, Type: BYTES, Flags: PUBLIC - UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x00CC, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x00CD, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x00CE, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x00CF, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x00D0, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x00D1, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x00D2, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x00D3, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x00D4, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x00DB, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x00E2, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY - UNIT_FIELD_PADDING = OBJECT_END + 0x00E3, // Size: 1, Type: INT, Flags: NONE - UNIT_END = OBJECT_END + 0x00E4, + UNIT_FIELD_BYTES_0 = OBJECT_END + 0x0010, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_HEALTH = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER1 = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER2 = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER3 = OBJECT_END + 0x0014, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER4 = OBJECT_END + 0x0015, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER5 = OBJECT_END + 0x0016, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER6 = OBJECT_END + 0x0017, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER7 = OBJECT_END + 0x0018, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXHEALTH = OBJECT_END + 0x0019, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER1 = OBJECT_END + 0x001A, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER2 = OBJECT_END + 0x001B, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER3 = OBJECT_END + 0x001C, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER4 = OBJECT_END + 0x001D, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER5 = OBJECT_END + 0x001E, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER6 = OBJECT_END + 0x001F, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MAXPOWER7 = OBJECT_END + 0x0020, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER = OBJECT_END + 0x0021, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER = OBJECT_END + 0x0028, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_LEVEL = OBJECT_END + 0x002F, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_FACTIONTEMPLATE = OBJECT_END + 0x0030, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_VIRTUAL_ITEM_SLOT_ID = OBJECT_END + 0x0031, // Size: 3, Type: INT, Flags: PUBLIC + UNIT_FIELD_FLAGS = OBJECT_END + 0x0034, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_FLAGS_2 = OBJECT_END + 0x0035, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_AURASTATE = OBJECT_END + 0x0036, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_BASEATTACKTIME = OBJECT_END + 0x0037, // Size: 2, Type: INT, Flags: PUBLIC + UNIT_FIELD_RANGEDATTACKTIME = OBJECT_END + 0x0039, // Size: 1, Type: INT, Flags: PRIVATE + UNIT_FIELD_BOUNDINGRADIUS = OBJECT_END + 0x003A, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_FIELD_COMBATREACH = OBJECT_END + 0x003B, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_FIELD_DISPLAYID = OBJECT_END + 0x003C, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_NATIVEDISPLAYID = OBJECT_END + 0x003D, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MOUNTDISPLAYID = OBJECT_END + 0x003E, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_MINDAMAGE = OBJECT_END + 0x003F, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_MAXDAMAGE = OBJECT_END + 0x0040, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_MINOFFHANDDAMAGE = OBJECT_END + 0x0041, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_MAXOFFHANDDAMAGE = OBJECT_END + 0x0042, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_BYTES_1 = OBJECT_END + 0x0043, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_PETNUMBER = OBJECT_END + 0x0044, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_PET_NAME_TIMESTAMP = OBJECT_END + 0x0045, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_PETEXPERIENCE = OBJECT_END + 0x0046, // Size: 1, Type: INT, Flags: OWNER_ONLY + UNIT_FIELD_PETNEXTLEVELEXP = OBJECT_END + 0x0047, // Size: 1, Type: INT, Flags: OWNER_ONLY + UNIT_DYNAMIC_FLAGS = OBJECT_END + 0x0048, // Size: 1, Type: INT, Flags: DYNAMIC + UNIT_CHANNEL_SPELL = OBJECT_END + 0x0049, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_MOD_CAST_SPEED = OBJECT_END + 0x004A, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_CREATED_BY_SPELL = OBJECT_END + 0x004B, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_NPC_FLAGS = OBJECT_END + 0x004C, // Size: 1, Type: INT, Flags: DYNAMIC + UNIT_NPC_EMOTESTATE = OBJECT_END + 0x004D, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_STAT0 = OBJECT_END + 0x004E, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT1 = OBJECT_END + 0x004F, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT2 = OBJECT_END + 0x0050, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT3 = OBJECT_END + 0x0051, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_STAT4 = OBJECT_END + 0x0052, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT0 = OBJECT_END + 0x0053, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT1 = OBJECT_END + 0x0054, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT2 = OBJECT_END + 0x0055, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT3 = OBJECT_END + 0x0056, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POSSTAT4 = OBJECT_END + 0x0057, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT0 = OBJECT_END + 0x0058, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT1 = OBJECT_END + 0x0059, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT2 = OBJECT_END + 0x005A, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT3 = OBJECT_END + 0x005B, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_NEGSTAT4 = OBJECT_END + 0x005C, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RESISTANCES = OBJECT_END + 0x005D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY, UNK3 + UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE = OBJECT_END + 0x0064, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE = OBJECT_END + 0x006B, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_BASE_MANA = OBJECT_END + 0x0072, // Size: 1, Type: INT, Flags: PUBLIC + UNIT_FIELD_BASE_HEALTH = OBJECT_END + 0x0073, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_BYTES_2 = OBJECT_END + 0x0074, // Size: 1, Type: BYTES, Flags: PUBLIC + UNIT_FIELD_ATTACK_POWER = OBJECT_END + 0x0075, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_ATTACK_POWER_MODS = OBJECT_END + 0x0076, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x0077, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RANGED_ATTACK_POWER = OBJECT_END + 0x0078, // Size: 1, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RANGED_ATTACK_POWER_MODS = OBJECT_END + 0x0079, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = OBJECT_END + 0x007A, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_MINRANGEDDAMAGE = OBJECT_END + 0x007B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_MAXRANGEDDAMAGE = OBJECT_END + 0x007C, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POWER_COST_MODIFIER = OBJECT_END + 0x007D, // Size: 7, Type: INT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_POWER_COST_MULTIPLIER = OBJECT_END + 0x0084, // Size: 7, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_MAXHEALTHMODIFIER = OBJECT_END + 0x008B, // Size: 1, Type: FLOAT, Flags: PRIVATE, OWNER_ONLY + UNIT_FIELD_HOVERHEIGHT = OBJECT_END + 0x008C, // Size: 1, Type: FLOAT, Flags: PUBLIC + UNIT_FIELD_PADDING = OBJECT_END + 0x008D, // Size: 1, Type: INT, Flags: NONE + UNIT_END = OBJECT_END + 0x008E, PLAYER_DUEL_ARBITER = UNIT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC PLAYER_FLAGS = UNIT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC @@ -262,160 +287,184 @@ enum EUnitFields PLAYER_QUEST_LOG_25_3 = UNIT_END + 0x006C, // Size: 1, Type: BYTES, Flags: PRIVATE PLAYER_QUEST_LOG_25_4 = UNIT_END + 0x006D, // Size: 1, Type: INT, Flags: PRIVATE PLAYER_VISIBLE_ITEM_1_CREATOR = UNIT_END + 0x006E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_1_0 = UNIT_END + 0x0070, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_1_PROPERTIES = UNIT_END + 0x007C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_1_PAD = UNIT_END + 0x007D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_2_CREATOR = UNIT_END + 0x007E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_2_0 = UNIT_END + 0x0080, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_2_PROPERTIES = UNIT_END + 0x008C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_2_PAD = UNIT_END + 0x008D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_3_CREATOR = UNIT_END + 0x008E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_3_0 = UNIT_END + 0x0090, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_3_PROPERTIES = UNIT_END + 0x009C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_3_PAD = UNIT_END + 0x009D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_4_CREATOR = UNIT_END + 0x009E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_4_0 = UNIT_END + 0x00A0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_4_PROPERTIES = UNIT_END + 0x00AC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_4_PAD = UNIT_END + 0x00AD, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_5_CREATOR = UNIT_END + 0x00AE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_5_0 = UNIT_END + 0x00B0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_5_PROPERTIES = UNIT_END + 0x00BC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_5_PAD = UNIT_END + 0x00BD, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_6_CREATOR = UNIT_END + 0x00BE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_6_0 = UNIT_END + 0x00C0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_6_PROPERTIES = UNIT_END + 0x00CC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_6_PAD = UNIT_END + 0x00CD, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_7_CREATOR = UNIT_END + 0x00CE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_7_0 = UNIT_END + 0x00D0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_7_PROPERTIES = UNIT_END + 0x00DC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_7_PAD = UNIT_END + 0x00DD, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_8_CREATOR = UNIT_END + 0x00DE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_8_0 = UNIT_END + 0x00E0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_8_PROPERTIES = UNIT_END + 0x00EC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_8_PAD = UNIT_END + 0x00ED, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_9_CREATOR = UNIT_END + 0x00EE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_9_0 = UNIT_END + 0x00F0, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_9_PROPERTIES = UNIT_END + 0x00FC, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_9_PAD = UNIT_END + 0x00FD, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_10_CREATOR = UNIT_END + 0x00FE, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_10_0 = UNIT_END + 0x0100, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_10_PROPERTIES = UNIT_END + 0x010C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_10_PAD = UNIT_END + 0x010D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_11_CREATOR = UNIT_END + 0x010E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_11_0 = UNIT_END + 0x0110, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_11_PROPERTIES = UNIT_END + 0x011C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_11_PAD = UNIT_END + 0x011D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_12_CREATOR = UNIT_END + 0x011E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_12_0 = UNIT_END + 0x0120, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_12_PROPERTIES = UNIT_END + 0x012C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_12_PAD = UNIT_END + 0x012D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_13_CREATOR = UNIT_END + 0x012E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_13_0 = UNIT_END + 0x0130, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_13_PROPERTIES = UNIT_END + 0x013C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_13_PAD = UNIT_END + 0x013D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_14_CREATOR = UNIT_END + 0x013E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_14_0 = UNIT_END + 0x0140, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_14_PROPERTIES = UNIT_END + 0x014C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_14_PAD = UNIT_END + 0x014D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_15_CREATOR = UNIT_END + 0x014E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_15_0 = UNIT_END + 0x0150, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_15_PROPERTIES = UNIT_END + 0x015C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_15_PAD = UNIT_END + 0x015D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_16_CREATOR = UNIT_END + 0x015E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_16_0 = UNIT_END + 0x0160, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_16_PROPERTIES = UNIT_END + 0x016C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_16_PAD = UNIT_END + 0x016D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_17_CREATOR = UNIT_END + 0x016E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_17_0 = UNIT_END + 0x0170, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_17_PROPERTIES = UNIT_END + 0x017C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_17_PAD = UNIT_END + 0x017D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_18_CREATOR = UNIT_END + 0x017E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_18_0 = UNIT_END + 0x0180, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_18_PROPERTIES = UNIT_END + 0x018C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_18_PAD = UNIT_END + 0x018D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_19_CREATOR = UNIT_END + 0x018E, // Size: 2, Type: LONG, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_19_0 = UNIT_END + 0x0190, // Size: 12, Type: INT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_19_PROPERTIES = UNIT_END + 0x019C, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC - PLAYER_VISIBLE_ITEM_19_PAD = UNIT_END + 0x019D, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_CHOSEN_TITLE = UNIT_END + 0x019E, // Size: 1, Type: INT, Flags: PUBLIC - PLAYER_FIELD_PAD_0 = UNIT_END + 0x019F, // Size: 1, Type: INT, Flags: NONE - PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x01A0, // Size: 46, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x01CE, // Size: 32, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x01EE, // Size: 56, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x0226, // Size: 14, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x0234, // Size: 24, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x024C, // Size: 64, Type: LONG, Flags: PRIVATE - PLAYER_FIELD_VANITYPET_SLOT_1 = UNIT_END + 0x028C, // Size: 36, Type: LONG, Flags: PRIVATE - PLAYER_FARSIGHT = UNIT_END + 0x02B0, // Size: 2, Type: LONG, Flags: PRIVATE - PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x02B2, // Size: 2, Type: LONG, Flags: PRIVATE - PLAYER_XP = UNIT_END + 0x02B4, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x02B5, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x02B6, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x0436, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x0437, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_TRACK_CREATURES = UNIT_END + 0x0438, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_TRACK_RESOURCES = UNIT_END + 0x0439, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x043A, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x043B, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x043C, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_EXPERTISE = UNIT_END + 0x043D, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x043E, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x043F, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x0440, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x0441, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x0442, // Size: 7, Type: FLOAT, Flags: PRIVATE - PLAYER_SHIELD_BLOCK = UNIT_END + 0x0449, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x044A, // Size: 128, Type: BYTES, Flags: PRIVATE - PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x04CA, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_COINAGE = UNIT_END + 0x04CB, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x04CC, // Size: 7, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x04D3, // Size: 7, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x04DA, // Size: 7, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x04E1, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x04E2, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x04E3, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BYTES = UNIT_END + 0x04E4, // Size: 1, Type: BYTES, Flags: PRIVATE - PLAYER_AMMO_ID = UNIT_END + 0x04E5, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_SELF_RES_SPELL = UNIT_END + 0x04E6, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x04E7, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x04E8, // Size: 12, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x04F4, // Size: 12, Type: INT, Flags: PRIVATE - PLAYER_FIELD_KILLS = UNIT_END + 0x0500, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE - PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x0501, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x0502, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_LIFETIME_HONORBALE_KILLS = UNIT_END + 0x0503, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_BYTES2 = UNIT_END + 0x0504, // Size: 1, Type: BYTES, Flags: PRIVATE - PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x0505, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x0506, // Size: 24, Type: INT, Flags: PRIVATE - PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x051E, // Size: 18, Type: INT, Flags: PRIVATE - PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x0530, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x0531, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_MOD_MANA_REGEN = UNIT_END + 0x0532, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_FIELD_MOD_MANA_REGEN_INTERRUPT = UNIT_END + 0x0533, // Size: 1, Type: FLOAT, Flags: PRIVATE - PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x0534, // Size: 1, Type: INT, Flags: PRIVATE - PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x0535, // Size: 25, Type: INT, Flags: PRIVATE - PLAYER_END = UNIT_END + 0x054E, + PLAYER_VISIBLE_ITEM_1_0 = UNIT_END + 0x0070, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_1_PROPERTIES = UNIT_END + 0x007D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_1_SEED = UNIT_END + 0x007E, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_1_PAD = UNIT_END + 0x007F, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_CREATOR = UNIT_END + 0x0080, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_0 = UNIT_END + 0x0082, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_PROPERTIES = UNIT_END + 0x008F, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_SEED = UNIT_END + 0x0090, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_2_PAD = UNIT_END + 0x0091, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_CREATOR = UNIT_END + 0x0092, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_0 = UNIT_END + 0x0094, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_PROPERTIES = UNIT_END + 0x00A1, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_SEED = UNIT_END + 0x00A2, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_3_PAD = UNIT_END + 0x00A3, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_CREATOR = UNIT_END + 0x00A4, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_0 = UNIT_END + 0x00A6, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_PROPERTIES = UNIT_END + 0x00B3, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_SEED = UNIT_END + 0x00B4, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_4_PAD = UNIT_END + 0x00B5, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_CREATOR = UNIT_END + 0x00B6, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_0 = UNIT_END + 0x00B8, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_PROPERTIES = UNIT_END + 0x00C5, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_SEED = UNIT_END + 0x00C6, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_5_PAD = UNIT_END + 0x00C7, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_CREATOR = UNIT_END + 0x00C8, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_0 = UNIT_END + 0x00CA, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_PROPERTIES = UNIT_END + 0x00D7, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_SEED = UNIT_END + 0x00D8, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_6_PAD = UNIT_END + 0x00D9, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_CREATOR = UNIT_END + 0x00DA, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_0 = UNIT_END + 0x00DC, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_PROPERTIES = UNIT_END + 0x00E9, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_SEED = UNIT_END + 0x00EA, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_7_PAD = UNIT_END + 0x00EB, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_CREATOR = UNIT_END + 0x00EC, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_0 = UNIT_END + 0x00EE, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_PROPERTIES = UNIT_END + 0x00FB, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_SEED = UNIT_END + 0x00FC, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_8_PAD = UNIT_END + 0x00FD, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_CREATOR = UNIT_END + 0x00FE, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_0 = UNIT_END + 0x0100, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_PROPERTIES = UNIT_END + 0x010D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_SEED = UNIT_END + 0x010E, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_9_PAD = UNIT_END + 0x010F, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_CREATOR = UNIT_END + 0x0110, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_0 = UNIT_END + 0x0112, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_PROPERTIES = UNIT_END + 0x011F, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_SEED = UNIT_END + 0x0120, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_10_PAD = UNIT_END + 0x0121, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_CREATOR = UNIT_END + 0x0122, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_0 = UNIT_END + 0x0124, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_PROPERTIES = UNIT_END + 0x0131, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_SEED = UNIT_END + 0x0132, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_11_PAD = UNIT_END + 0x0133, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_CREATOR = UNIT_END + 0x0134, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_0 = UNIT_END + 0x0136, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_PROPERTIES = UNIT_END + 0x0143, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_SEED = UNIT_END + 0x0144, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_12_PAD = UNIT_END + 0x0145, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_CREATOR = UNIT_END + 0x0146, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_0 = UNIT_END + 0x0148, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_PROPERTIES = UNIT_END + 0x0155, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_SEED = UNIT_END + 0x0156, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_13_PAD = UNIT_END + 0x0157, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_CREATOR = UNIT_END + 0x0158, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_0 = UNIT_END + 0x015A, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_PROPERTIES = UNIT_END + 0x0167, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_SEED = UNIT_END + 0x0168, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_14_PAD = UNIT_END + 0x0169, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_CREATOR = UNIT_END + 0x016A, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_0 = UNIT_END + 0x016C, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_PROPERTIES = UNIT_END + 0x0179, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_SEED = UNIT_END + 0x017A, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_15_PAD = UNIT_END + 0x017B, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_CREATOR = UNIT_END + 0x017C, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_0 = UNIT_END + 0x017E, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_PROPERTIES = UNIT_END + 0x018B, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_SEED = UNIT_END + 0x018C, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_16_PAD = UNIT_END + 0x018D, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_CREATOR = UNIT_END + 0x018E, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_0 = UNIT_END + 0x0190, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_PROPERTIES = UNIT_END + 0x019D, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_SEED = UNIT_END + 0x019E, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_17_PAD = UNIT_END + 0x019F, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_CREATOR = UNIT_END + 0x01A0, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_0 = UNIT_END + 0x01A2, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_PROPERTIES = UNIT_END + 0x01AF, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_SEED = UNIT_END + 0x01B0, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_18_PAD = UNIT_END + 0x01B1, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_CREATOR = UNIT_END + 0x01B2, // Size: 2, Type: LONG, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_0 = UNIT_END + 0x01B4, // Size: 13, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_PROPERTIES = UNIT_END + 0x01C1, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_SEED = UNIT_END + 0x01C2, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_VISIBLE_ITEM_19_PAD = UNIT_END + 0x01C3, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_CHOSEN_TITLE = UNIT_END + 0x01C4, // Size: 1, Type: INT, Flags: PUBLIC + PLAYER_FIELD_PAD_0 = UNIT_END + 0x01C5, // Size: 1, Type: INT, Flags: NONE + PLAYER_FIELD_INV_SLOT_HEAD = UNIT_END + 0x01C6, // Size: 46, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_PACK_SLOT_1 = UNIT_END + 0x01F4, // Size: 32, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_BANK_SLOT_1 = UNIT_END + 0x0214, // Size: 56, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_BANKBAG_SLOT_1 = UNIT_END + 0x024C, // Size: 14, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_VENDORBUYBACK_SLOT_1 = UNIT_END + 0x025A, // Size: 24, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_KEYRING_SLOT_1 = UNIT_END + 0x0272, // Size: 64, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_VANITYPET_SLOT_1 = UNIT_END + 0x02B2, // Size: 36, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_CURRENCYTOKEN_SLOT_1 = UNIT_END + 0x02D6, // Size: 64, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_QUESTBAG_SLOT_1 = UNIT_END + 0x0316, // Size: 64, Type: LONG, Flags: PRIVATE + PLAYER_FARSIGHT = UNIT_END + 0x0356, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER__FIELD_KNOWN_TITLES = UNIT_END + 0x0358, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER__FIELD_KNOWN_TITLES1 = UNIT_END + 0x035A, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER_FIELD_KNOWN_CURRENCIES = UNIT_END + 0x035C, // Size: 2, Type: LONG, Flags: PRIVATE + PLAYER_XP = UNIT_END + 0x035E, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_NEXT_LEVEL_XP = UNIT_END + 0x035F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_SKILL_INFO_1_1 = UNIT_END + 0x0360, // Size: 384, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_CHARACTER_POINTS1 = UNIT_END + 0x04E0, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_CHARACTER_POINTS2 = UNIT_END + 0x04E1, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_TRACK_CREATURES = UNIT_END + 0x04E2, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_TRACK_RESOURCES = UNIT_END + 0x04E3, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_BLOCK_PERCENTAGE = UNIT_END + 0x04E4, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_DODGE_PERCENTAGE = UNIT_END + 0x04E5, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_PARRY_PERCENTAGE = UNIT_END + 0x04E6, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_EXPERTISE = UNIT_END + 0x04E7, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_OFFHAND_EXPERTISE = UNIT_END + 0x04E8, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_CRIT_PERCENTAGE = UNIT_END + 0x04E9, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_RANGED_CRIT_PERCENTAGE = UNIT_END + 0x04EA, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_OFFHAND_CRIT_PERCENTAGE = UNIT_END + 0x04EB, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_SPELL_CRIT_PERCENTAGE1 = UNIT_END + 0x04EC, // Size: 7, Type: FLOAT, Flags: PRIVATE + PLAYER_SHIELD_BLOCK = UNIT_END + 0x04F3, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_SHIELD_BLOCK_CRIT_PERCENTAGE = UNIT_END + 0x04F4, // Size: 1, Type: FLOAT, Flags: PRIVATE + PLAYER_EXPLORED_ZONES_1 = UNIT_END + 0x04F5, // Size: 128, Type: BYTES, Flags: PRIVATE + PLAYER_REST_STATE_EXPERIENCE = UNIT_END + 0x0575, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_COINAGE = UNIT_END + 0x0576, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_POS = UNIT_END + 0x0577, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_NEG = UNIT_END + 0x057E, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_DAMAGE_DONE_PCT = UNIT_END + 0x0585, // Size: 7, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_HEALING_DONE_POS = UNIT_END + 0x058C, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_TARGET_RESISTANCE = UNIT_END + 0x058D, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MOD_TARGET_PHYSICAL_RESISTANCE = UNIT_END + 0x058E, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BYTES = UNIT_END + 0x058F, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_AMMO_ID = UNIT_END + 0x0590, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_SELF_RES_SPELL = UNIT_END + 0x0591, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_PVP_MEDALS = UNIT_END + 0x0592, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BUYBACK_PRICE_1 = UNIT_END + 0x0593, // Size: 12, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BUYBACK_TIMESTAMP_1 = UNIT_END + 0x059F, // Size: 12, Type: INT, Flags: PRIVATE + PLAYER_FIELD_KILLS = UNIT_END + 0x05AB, // Size: 1, Type: TWO_SHORT, Flags: PRIVATE + PLAYER_FIELD_TODAY_CONTRIBUTION = UNIT_END + 0x05AC, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_YESTERDAY_CONTRIBUTION = UNIT_END + 0x05AD, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_LIFETIME_HONORBALE_KILLS = UNIT_END + 0x05AE, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_BYTES2 = UNIT_END + 0x05AF, // Size: 1, Type: BYTES, Flags: PRIVATE + PLAYER_FIELD_WATCHED_FACTION_INDEX = UNIT_END + 0x05B0, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_COMBAT_RATING_1 = UNIT_END + 0x05B1, // Size: 25, Type: INT, Flags: PRIVATE + PLAYER_FIELD_ARENA_TEAM_INFO_1_1 = UNIT_END + 0x05CA, // Size: 18, Type: INT, Flags: PRIVATE + PLAYER_FIELD_HONOR_CURRENCY = UNIT_END + 0x05DC, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_ARENA_CURRENCY = UNIT_END + 0x05DD, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_MAX_LEVEL = UNIT_END + 0x05DE, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_FIELD_DAILY_QUESTS_1 = UNIT_END + 0x05DF, // Size: 25, Type: INT, Flags: PRIVATE + PLAYER_RUNE_REGEN_1 = UNIT_END + 0x05F8, // Size: 4, Type: FLOAT, Flags: PRIVATE + PLAYER_NO_REAGENT_COST_1 = UNIT_END + 0x05FC, // Size: 3, Type: INT, Flags: PRIVATE + PLAYER_FIELD_GLYPH_SLOTS_1 = UNIT_END + 0x05FF, // Size: 8, Type: INT, Flags: PRIVATE + PLAYER_FIELD_GLYPHS_1 = UNIT_END + 0x0607, // Size: 8, Type: INT, Flags: PRIVATE + PLAYER_GLYPHS_ENABLED = UNIT_END + 0x060F, // Size: 1, Type: INT, Flags: PRIVATE + PLAYER_END = UNIT_END + 0x0610, }; enum EGameObjectFields { OBJECT_FIELD_CREATED_BY = OBJECT_END + 0x0000, // Size: 2, Type: LONG, Flags: PUBLIC GAMEOBJECT_DISPLAYID = OBJECT_END + 0x0002, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_ROTATION = OBJECT_END + 0x0004, // Size: 4, Type: FLOAT, Flags: PUBLIC - GAMEOBJECT_STATE = OBJECT_END + 0x0008, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_POS_X = OBJECT_END + 0x0009, // Size: 1, Type: FLOAT, Flags: PUBLIC - GAMEOBJECT_POS_Y = OBJECT_END + 0x000A, // Size: 1, Type: FLOAT, Flags: PUBLIC - GAMEOBJECT_POS_Z = OBJECT_END + 0x000B, // Size: 1, Type: FLOAT, Flags: PUBLIC - GAMEOBJECT_FACING = OBJECT_END + 0x000C, // Size: 1, Type: FLOAT, Flags: PUBLIC - GAMEOBJECT_DYN_FLAGS = OBJECT_END + 0x000D, // Size: 1, Type: INT, Flags: DYNAMIC - GAMEOBJECT_FACTION = OBJECT_END + 0x000E, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_TYPE_ID = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC + GAMEOBJECT_FLAGS = OBJECT_END + 0x0003, // Size: 1, Type: TWO_SHORT, Flags: PUBLIC + GAMEOBJECT_ROTATION = OBJECT_END + 0x0004, // Size: 2, Type: LONG, Flags: PUBLIC + GAMEOBJECT_PARENTROTATION = OBJECT_END + 0x0006, // Size: 4, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_POS_X = OBJECT_END + 0x000A, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_POS_Y = OBJECT_END + 0x000B, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_POS_Z = OBJECT_END + 0x000C, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_FACING = OBJECT_END + 0x000D, // Size: 1, Type: FLOAT, Flags: PUBLIC + GAMEOBJECT_DYNAMIC = OBJECT_END + 0x000E, // Size: 1, Type: TWO_SHORT, Flags: DYNAMIC + GAMEOBJECT_FACTION = OBJECT_END + 0x000F, // Size: 1, Type: INT, Flags: PUBLIC GAMEOBJECT_LEVEL = OBJECT_END + 0x0010, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_ARTKIT = OBJECT_END + 0x0011, // Size: 1, Type: INT, Flags: PUBLIC - GAMEOBJECT_ANIMPROGRESS = OBJECT_END + 0x0012, // Size: 1, Type: INT, Flags: DYNAMIC - GAMEOBJECT_PADDING = OBJECT_END + 0x0013, // Size: 1, Type: INT, Flags: NONE - GAMEOBJECT_END = OBJECT_END + 0x0014, + GAMEOBJECT_BYTES_1 = OBJECT_END + 0x0011, // Size: 1, Type: BYTES, Flags: PUBLIC + GAMEOBJECT_END = OBJECT_END + 0x0012, }; enum EDynamicObjectFields diff --git a/src/game/UpdateMask.h b/src/game/UpdateMask.h index 9949dd6aa5b..8909b23ed51 100644 --- a/src/game/UpdateMask.h +++ b/src/game/UpdateMask.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,27 +36,27 @@ class UpdateMask delete [] mUpdateMask; } - inline void SetBit (uint32 index) + void SetBit (uint32 index) { ( (uint8 *)mUpdateMask )[ index >> 3 ] |= 1 << ( index & 0x7 ); } - inline void UnsetBit (uint32 index) + void UnsetBit (uint32 index) { ( (uint8 *)mUpdateMask )[ index >> 3 ] &= (0xff ^ (1 << ( index & 0x7 ) ) ); } - inline bool GetBit (uint32 index) + bool GetBit (uint32 index) const { return ( ( (uint8 *)mUpdateMask)[ index >> 3 ] & ( 1 << ( index & 0x7 ) )) != 0; } - inline uint32 GetBlockCount() { return mBlocks; } - inline uint32 GetLength() { return mBlocks << 2; } - inline uint32 GetCount() { return mCount; } - inline uint8* GetMask() { return (uint8*)mUpdateMask; } + uint32 GetBlockCount() const { return mBlocks; } + uint32 GetLength() const { return mBlocks << 2; } + uint32 GetCount() const { return mCount; } + uint8* GetMask() { return (uint8*)mUpdateMask; } - inline void SetCount (uint32 valuesCount) + void SetCount (uint32 valuesCount) { if(mUpdateMask) delete [] mUpdateMask; @@ -68,13 +68,13 @@ class UpdateMask memset(mUpdateMask, 0, mBlocks << 2); } - inline void Clear() + void Clear() { if (mUpdateMask) memset(mUpdateMask, 0, mBlocks << 2); } - inline UpdateMask& operator = ( const UpdateMask& mask ) + UpdateMask& operator = ( const UpdateMask& mask ) { SetCount(mask.mCount); memcpy(mUpdateMask, mask.mUpdateMask, mBlocks << 2); @@ -82,21 +82,21 @@ class UpdateMask return *this; } - inline void operator &= ( const UpdateMask& mask ) + void operator &= ( const UpdateMask& mask ) { ASSERT(mask.mCount <= mCount); for (uint32 i = 0; i < mBlocks; i++) mUpdateMask[i] &= mask.mUpdateMask[i]; } - inline void operator |= ( const UpdateMask& mask ) + void operator |= ( const UpdateMask& mask ) { ASSERT(mask.mCount <= mCount); for (uint32 i = 0; i < mBlocks; i++) mUpdateMask[i] |= mask.mUpdateMask[i]; } - inline UpdateMask operator & ( const UpdateMask& mask ) const + UpdateMask operator & ( const UpdateMask& mask ) const { ASSERT(mask.mCount <= mCount); @@ -107,7 +107,7 @@ class UpdateMask return newmask; } - inline UpdateMask operator | ( const UpdateMask& mask ) const + UpdateMask operator | ( const UpdateMask& mask ) const { ASSERT(mask.mCount <= mCount); diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp new file mode 100644 index 00000000000..b533609d763 --- /dev/null +++ b/src/game/Vehicle.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" +#include "Log.h" +#include "WorldSession.h" +#include "WorldPacket.h" +#include "ObjectMgr.h" +#include "SpellMgr.h" +#include "Vehicle.h" +#include "MapManager.h" +#include "SpellAuras.h" +#include "Unit.h" +#include "Util.h" + +Vehicle::Vehicle() : Creature(), m_vehicleId(0) +{ + m_isVehicle = true; + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_VEHICLE); +} + +Vehicle::~Vehicle() +{ + if(m_uint32Values) // only for fully created Object + ObjectAccessor::Instance().RemoveObject(this); +} + +void Vehicle::AddToWorld() +{ + ///- Register the vehicle for guid lookup + if(!IsInWorld()) ObjectAccessor::Instance().AddObject(this); + Unit::AddToWorld(); +} + +void Vehicle::RemoveFromWorld() +{ + ///- Remove the vehicle from the accessor + if(IsInWorld()) ObjectAccessor::Instance().RemoveObject(this); + ///- Don't call the function for Creature, normal mobs + totems go in a different storage + Unit::RemoveFromWorld(); +} + +void Vehicle::setDeathState(DeathState s) // overwrite virtual Creature::setDeathState and Unit::setDeathState +{ + Creature::setDeathState(s); +} + +void Vehicle::Update(uint32 diff) +{ + Creature::Update(diff); +} + +bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team) +{ + SetMapId(map->GetId()); + SetInstanceId(map->GetInstanceId()); + + Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE); + + if(!InitEntry(Entry, team)) + return false; + + m_defaultMovementType = IDLE_MOTION_TYPE; + + AIM_Initialize(); + + SetVehicleId(vehicleId); + + SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); + + CreatureInfo const *ci = GetCreatureInfo(); + setFaction(team == ALLIANCE ? ci->faction_A : ci->faction_H); + SetMaxHealth(ci->maxhealth); + SelectLevel(ci); + SetHealth(GetMaxHealth()); + + return true; +} + +void Vehicle::Dismiss() +{ + SendObjectDeSpawnAnim(GetGUID()); + CombatStop(); + CleanupsBeforeDelete(); + AddObjectToRemoveList(); +} diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h new file mode 100644 index 00000000000..6d9c7cd7943 --- /dev/null +++ b/src/game/Vehicle.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef MANGOSSERVER_VEHICLE_H +#define MANGOSSERVER_VEHICLE_H + +#include "ObjectDefines.h" +#include "Creature.h" +#include "Unit.h" + +class Vehicle : public Creature +{ + public: + explicit Vehicle(); + virtual ~Vehicle(); + + void AddToWorld(); + void RemoveFromWorld(); + + bool Create (uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team); + + void setDeathState(DeathState s); // overwrite virtual Creature::setDeathState and Unit::setDeathState + void Update(uint32 diff); // overwrite virtual Creature::Update and Unit::Update + + uint32 GetVehicleId() { return m_vehicleId; } + void SetVehicleId(uint32 vehicleid) { m_vehicleId = vehicleid; } + + void Dismiss(); + + protected: + uint32 m_vehicleId; + + private: + void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called + { + assert(false); + } + void DeleteFromDB() // overwrited of Creature::DeleteFromDB - don't must be called + { + assert(false); + } +}; +#endif diff --git a/src/game/VoiceChatHandler.cpp b/src/game/VoiceChatHandler.cpp index f75678f305f..ddc178a8694 100644 --- a/src/game/VoiceChatHandler.cpp +++ b/src/game/VoiceChatHandler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/WaypointManager.cpp b/src/game/WaypointManager.cpp index 8a9de3849c4..6e303ca3053 100644 --- a/src/game/WaypointManager.cpp +++ b/src/game/WaypointManager.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/WaypointManager.h b/src/game/WaypointManager.h index 2e1ac25c369..e9787090ede 100644 --- a/src/game/WaypointManager.h +++ b/src/game/WaypointManager.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp index 5a3b1eee8e2..e5b625fb6e5 100644 --- a/src/game/WaypointMovementGenerator.cpp +++ b/src/game/WaypointMovementGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/WaypointMovementGenerator.h b/src/game/WaypointMovementGenerator.h index b8f72bb5dbf..5b5df75d31e 100644 --- a/src/game/WaypointMovementGenerator.h +++ b/src/game/WaypointMovementGenerator.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -48,7 +48,7 @@ class TRINITY_DLL_SPEC PathMovementBase PathMovementBase() : i_currentNode(0) {} virtual ~PathMovementBase() {}; - inline bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); } + bool MovementInProgress(void) const { return i_currentNode < i_path.Size(); } void LoadPath(T &); void ReloadPath(T &); @@ -109,7 +109,7 @@ public PathMovementBase<Player> Path& GetPath() { return i_path; } uint32 GetPathAtMapEnd() const; - inline bool HasArrived() const { return (i_currentNode >= i_path.Size()); } + bool HasArrived() const { return (i_currentNode >= i_path.Size()); } void SetCurrentNodeAfterTeleport(); void SkipCurrentNode() { ++i_currentNode; } bool GetDestination(float& x, float& y, float& z) const { i_destinationHolder.GetDestination(x,y,z); return true; } diff --git a/src/game/Weather.cpp b/src/game/Weather.cpp index d825b2f4064..9fd91764ca3 100644 --- a/src/game/Weather.cpp +++ b/src/game/Weather.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,7 +42,7 @@ Weather::Weather(uint32 zone, WeatherZoneChances const* weatherChances) : m_zone } /// Launch a weather update -bool Weather::Update(time_t diff) +bool Weather::Update(uint32 diff) { if (m_timer.GetCurrent()>=0) m_timer.Update(diff); diff --git a/src/game/Weather.h b/src/game/Weather.h index 7fc3068ffe7..fd04d6b6abd 100644 --- a/src/game/Weather.h +++ b/src/game/Weather.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -62,7 +62,7 @@ class Weather void SetWeather(WeatherType type, float grade); /// For which zone is this weather? uint32 GetZone() { return m_zone; }; - bool Update(time_t diff); + bool Update(uint32 diff); private: WeatherState GetWeatherState() const; uint32 m_zone; diff --git a/src/game/World.cpp b/src/game/World.cpp index e494d041b5f..97938058d27 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +37,7 @@ #include "SkillDiscovery.h" #include "World.h" #include "AccountMgr.h" +#include "AchievementMgr.h" #include "ObjectMgr.h" #include "SpellMgr.h" #include "Chat.h" @@ -237,7 +238,7 @@ World::AddSession_ (WorldSession* s) uint32 Sessions = GetActiveAndQueuedSessionCount (); uint32 pLimit = GetPlayerAmountLimit (); - uint32 QueueSize = GetQueueSize (); //number of players in the queue + uint32 QueueSize = GetQueueSize (); //number of players in the queue //so we don't count the user trying to //login as a session and queue the socket that we are using @@ -254,10 +255,10 @@ World::AddSession_ (WorldSession* s) WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); packet << uint8 (AUTH_OK); - packet << uint32 (0); // unknown random value... - packet << uint8 (0); - packet << uint32 (0); - packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account + packet << uint32 (0); // BillingTimeRemaining + packet << uint8 (0); // BillingPlanFlags + packet << uint32 (0); // BillingTimeRested + packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account s->SendPacket (&packet); UpdateMaxSessionCounters (); @@ -265,7 +266,7 @@ World::AddSession_ (WorldSession* s) // Updates the population if (pLimit > 0) { - float popu = GetActiveSessionCount (); //updated number of users on the server + float popu = GetActiveSessionCount (); //updated number of users on the server popu /= pLimit; popu *= 2; LoginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID); @@ -292,10 +293,10 @@ void World::AddQueuedPlayer(WorldSession* sess) // The 1st SMSG_AUTH_RESPONSE needs to contain other info too. WorldPacket packet (SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); packet << uint8 (AUTH_WAIT_QUEUE); - packet << uint32 (0); // unknown random value... - packet << uint8 (0); - packet << uint32 (0); - packet << uint8 (sess->Expansion () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account + packet << uint32 (0); // BillingTimeRemaining + packet << uint8 (0); // BillingPlanFlags + packet << uint32 (0); // BillingTimeRested + packet << uint8 (sess->Expansion () ? 1 : 0); // 0 - normal, 1 - TBC, must be set in database manually for each account packet << uint32(GetQueuePos (sess)); sess->SendPacket (&packet); @@ -419,24 +420,30 @@ void World::LoadConfigSettings(bool reload) rate_values[RATE_HEALTH] = sConfig.GetFloatDefault("Rate.Health", 1); if(rate_values[RATE_HEALTH] < 0) { - sLog.outError("Rate.Health (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_HEALTH]); + sLog.outError("Rate.Health (%f) must be > 0. Using 1 instead.",rate_values[RATE_HEALTH]); rate_values[RATE_HEALTH] = 1; } rate_values[RATE_POWER_MANA] = sConfig.GetFloatDefault("Rate.Mana", 1); if(rate_values[RATE_POWER_MANA] < 0) { - sLog.outError("Rate.Mana (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_POWER_MANA]); + sLog.outError("Rate.Mana (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_MANA]); rate_values[RATE_POWER_MANA] = 1; } rate_values[RATE_POWER_RAGE_INCOME] = sConfig.GetFloatDefault("Rate.Rage.Income", 1); rate_values[RATE_POWER_RAGE_LOSS] = sConfig.GetFloatDefault("Rate.Rage.Loss", 1); if(rate_values[RATE_POWER_RAGE_LOSS] < 0) { - sLog.outError("Rate.Rage.Loss (%f) mustbe > 0. Using 1 instead.",rate_values[RATE_POWER_RAGE_LOSS]); + sLog.outError("Rate.Rage.Loss (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_RAGE_LOSS]); rate_values[RATE_POWER_RAGE_LOSS] = 1; } + rate_values[RATE_POWER_RUNICPOWER_INCOME] = sConfig.GetFloatDefault("Rate.RunicPower.Income", 1); + rate_values[RATE_POWER_RUNICPOWER_LOSS] = sConfig.GetFloatDefault("Rate.RunicPower.Loss", 1); + if(rate_values[RATE_POWER_RUNICPOWER_LOSS] < 0) + { + sLog.outError("Rate.RunicPower.Loss (%f) must be > 0. Using 1 instead.",rate_values[RATE_POWER_RUNICPOWER_LOSS]); + rate_values[RATE_POWER_RUNICPOWER_LOSS] = 1; + } rate_values[RATE_POWER_FOCUS] = sConfig.GetFloatDefault("Rate.Focus", 1.0f); - rate_values[RATE_LOYALTY] = sConfig.GetFloatDefault("Rate.Loyalty", 1.0f); rate_values[RATE_SKILL_DISCOVERY] = sConfig.GetFloatDefault("Rate.Skill.Discovery", 1.0f); rate_values[RATE_DROP_ITEM_POOR] = sConfig.GetFloatDefault("Rate.Drop.Item.Poor", 1.0f); rate_values[RATE_DROP_ITEM_NORMAL] = sConfig.GetFloatDefault("Rate.Drop.Item.Normal", 1.0f); @@ -450,7 +457,6 @@ void World::LoadConfigSettings(bool reload) rate_values[RATE_XP_KILL] = sConfig.GetFloatDefault("Rate.XP.Kill", 1.0f); rate_values[RATE_XP_QUEST] = sConfig.GetFloatDefault("Rate.XP.Quest", 1.0f); rate_values[RATE_XP_EXPLORE] = sConfig.GetFloatDefault("Rate.XP.Explore", 1.0f); - rate_values[RATE_XP_PAST_70] = sConfig.GetFloatDefault("Rate.XP.PastLevel70", 1.0f); rate_values[RATE_REPUTATION_GAIN] = sConfig.GetFloatDefault("Rate.Reputation.Gain", 1.0f); rate_values[RATE_CREATURE_NORMAL_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Normal.Damage", 1.0f); rate_values[RATE_CREATURE_ELITE_ELITE_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.Elite.Damage", 1.0f); @@ -629,6 +635,15 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = m_configs[CONFIG_CHARACTERS_PER_REALM]; } + m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("HeroicCharactersPerRealm", 1); + if(m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] < 0 || m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] > 10) + { + sLog.outError("HeroicCharactersPerRealm (%i) must be in range 0..10. Set to 1.",m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]); + m_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = 1; + } + + m_configs[CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING] = sConfig.GetIntDefault("MinLevelForHeroicCharacterCreating", 55); + m_configs[CONFIG_SKIP_CINEMATICS] = sConfig.GetIntDefault("SkipCinematics", 0); if(m_configs[CONFIG_SKIP_CINEMATICS] < 0 || m_configs[CONFIG_SKIP_CINEMATICS] > 2) { @@ -663,6 +678,20 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_START_PLAYER_LEVEL] = m_configs[CONFIG_MAX_PLAYER_LEVEL]; } + m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = sConfig.GetIntDefault("StartHeroicPlayerLevel", 55); + if(m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] < 1) + { + sLog.outError("StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to 55.", + m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL]); + m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = 55; + } + else if(m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] > m_configs[CONFIG_MAX_PLAYER_LEVEL]) + { + sLog.outError("StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.", + m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL],m_configs[CONFIG_MAX_PLAYER_LEVEL]); + m_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = m_configs[CONFIG_MAX_PLAYER_LEVEL]; + } + m_configs[CONFIG_START_PLAYER_MONEY] = sConfig.GetIntDefault("StartPlayerMoney", 0); if(m_configs[CONFIG_START_PLAYER_MONEY] < 0) { @@ -724,8 +753,11 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfig.GetBoolDefault("Instance.IgnoreRaid", false); m_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfig.GetBoolDefault("Battleground.CastDeserter", true); - m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", true); + m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", false); m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false); + m_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Arena.QueueAnnouncer.Enable", false); + m_configs[CONFIG_ARENA_SEASON_ID] = sConfig.GetIntDefault ("Arena.ArenaSeason.ID", 1); + m_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfig.GetBoolDefault("Arena.ArenaSeason.InProgress", true); m_configs[CONFIG_CAST_UNSTUCK] = sConfig.GetBoolDefault("CastUnstuck", true); m_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfig.GetIntDefault("Instance.ResetTimeHour", 4); @@ -735,15 +767,17 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_MIN_PETITION_SIGNS] = sConfig.GetIntDefault("MinPetitionSigns", 9); if(m_configs[CONFIG_MIN_PETITION_SIGNS] > 9) { - sLog.outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.",m_configs[CONFIG_MIN_PETITION_SIGNS]); + sLog.outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.", m_configs[CONFIG_MIN_PETITION_SIGNS]); m_configs[CONFIG_MIN_PETITION_SIGNS] = 9; } - m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState",2); - m_configs[CONFIG_GM_CHAT] = sConfig.GetIntDefault("GM.Chat",2); - m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetIntDefault("GM.WhisperingTo",2); - m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList",false); - m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList",false); + m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState", 2); + m_configs[CONFIG_GM_VISIBLE_STATE] = sConfig.GetIntDefault("GM.Visible", 2); + //m_configs[CONFIG_GM_ACCEPT_TICKETS] = sConfig.GetIntDefault("GM.AcceptTickets", 2); + m_configs[CONFIG_GM_CHAT] = sConfig.GetIntDefault("GM.Chat", 2); + m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetIntDefault("GM.WhisperingTo", 2); + m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList", false); + m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList", false); m_configs[CONFIG_GM_LOG_TRADE] = sConfig.GetBoolDefault("GM.LogTrade", false); m_configs[CONFIG_START_GM_LEVEL] = sConfig.GetIntDefault("GM.StartLevel", 1); if(m_configs[CONFIG_START_GM_LEVEL] < m_configs[CONFIG_START_PLAYER_LEVEL]) @@ -757,6 +791,8 @@ void World::LoadConfigSettings(bool reload) sLog.outError("GM.StartLevel (%i) must be in range 1..%u. Set to %u.", m_configs[CONFIG_START_GM_LEVEL], MAX_LEVEL, MAX_LEVEL); m_configs[CONFIG_START_GM_LEVEL] = MAX_LEVEL; } + m_configs[CONFIG_GM_LOWER_SECURITY] = sConfig.GetBoolDefault("GM.LowerSecurity", false); + m_configs[CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS] = sConfig.GetBoolDefault("GM.AllowAchievementGain", true); m_configs[CONFIG_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode",0); @@ -783,6 +819,7 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_SKILL_CHANCE_SKINNING_STEPS] = sConfig.GetIntDefault("SkillChance.SkinningSteps",75); m_configs[CONFIG_SKILL_PROSPECTING] = sConfig.GetBoolDefault("SkillChance.Prospecting",false); + m_configs[CONFIG_SKILL_MILLING] = sConfig.GetBoolDefault("SkillChance.Milling",false); m_configs[CONFIG_SKILL_GAIN_CRAFTING] = sConfig.GetIntDefault("SkillGain.Crafting", 1); if(m_configs[CONFIG_SKILL_GAIN_CRAFTING] < 0) @@ -871,6 +908,8 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_DEATH_SICKNESS_LEVEL] = sConfig.GetIntDefault("Death.SicknessLevel", 11); m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvP", true); m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvE", true); + m_configs[CONFIG_DEATH_BONES_WORLD] = sConfig.GetBoolDefault("Death.Bones.World", true); + m_configs[CONFIG_DEATH_BONES_BG_OR_ARENA] = sConfig.GetBoolDefault("Death.Bones.BattlegroundOrArena", true); m_configs[CONFIG_THREAT_RADIUS] = sConfig.GetIntDefault("ThreatRadius", 60); @@ -1069,7 +1108,7 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Script Names..."); objmgr.LoadScriptNames(); - sLog.outString( "Loading InstanceTemplate" ); + sLog.outString( "Loading InstanceTemplate..." ); objmgr.LoadInstanceTemplate(); sLog.outString( "Loading SkillLineAbilityMultiMap Data..." ); @@ -1077,11 +1116,12 @@ void World::SetInitialWorldSettings() ///- Clean up and pack instances sLog.outString( "Cleaning up instances..." ); - sInstanceSaveManager.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables + sInstanceSaveManager.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables sLog.outString( "Packing instances..." ); sInstanceSaveManager.PackInstances(); + sLog.outString(); sLog.outString( "Loading Localization strings..." ); objmgr.LoadCreatureLocales(); objmgr.LoadGameObjectLocales(); @@ -1091,6 +1131,8 @@ void World::SetInitialWorldSettings() objmgr.LoadPageTextLocales(); objmgr.LoadNpcOptionLocales(); objmgr.SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts) + sLog.outString( ">>> Localization strings loaded" ); + sLog.outString(); sLog.outString( "Loading Page Texts..." ); objmgr.LoadPageTexts(); @@ -1119,6 +1161,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Spell Proc Event conditions..." ); spellmgr.LoadSpellProcEvents(); + sLog.outString( "Loading Spell Bonus Data..." ); + spellmgr.LoadSpellBonusess(); + sLog.outString( "Loading Aggro Spells Definitions..."); spellmgr.LoadSpellThreats(); @@ -1156,7 +1201,10 @@ void World::SetInitialWorldSettings() objmgr.LoadCreatures(); sLog.outString( "Loading Creature Addon Data..." ); + sLog.outString(); objmgr.LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures() + sLog.outString( ">>> Creature Addon Data loaded" ); + sLog.outString(); sLog.outString( "Loading Creature Respawn Data..." ); // must be after PackInstances() objmgr.LoadCreatureRespawnTimes(); @@ -1168,7 +1216,10 @@ void World::SetInitialWorldSettings() objmgr.LoadGameobjectRespawnTimes(); sLog.outString( "Loading Game Event Data..."); + sLog.outString(); gameeventmgr.LoadFromDB(); + sLog.outString( ">>> Game Event Data loaded" ); + sLog.outString(); sLog.outString( "Loading Weather Data..." ); objmgr.LoadWeatherZoneChances(); @@ -1177,7 +1228,10 @@ void World::SetInitialWorldSettings() objmgr.LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables sLog.outString( "Loading Quests Relations..." ); + sLog.outString(); objmgr.LoadQuestRelations(); // must be after quest load + sLog.outString( ">>> Quests Relations loaded" ); + sLog.outString(); sLog.outString( "Loading AreaTrigger definitions..." ); objmgr.LoadAreaTriggerTeleports(); // must be after item template load @@ -1203,14 +1257,20 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading spell pet auras..." ); spellmgr.LoadSpellPetAuras(); + sLog.outString( "Loading pet levelup spells..." ); + spellmgr.LoadPetLevelupSpellMap(); + sLog.outString( "Loading spell extra attributes...(TODO)" ); spellmgr.LoadSpellCustomAttr(); sLog.outString( "Loading linked spells..." ); spellmgr.LoadSpellLinked(); - sLog.outString( "Loading player Create Info & Level Stats..." ); + sLog.outString( "Loading Player Create Info & Level Stats..." ); + sLog.outString(); objmgr.LoadPlayerInfo(); + sLog.outString( ">>> Player Create Info & Level Stats loaded" ); + sLog.outString(); sLog.outString( "Loading Exploration BaseXP Data..." ); objmgr.LoadExplorationBaseXP(); @@ -1231,7 +1291,10 @@ void World::SetInitialWorldSettings() objmgr.LoadSpellDisabledEntrys(); sLog.outString( "Loading Loot Tables..." ); + sLog.outString(); LoadLootTables(); + sLog.outString( ">>> Loot Tables loaded" ); + sLog.outString(); sLog.outString( "Loading Skill Discovery Table..." ); LoadSkillDiscoveryTable(); @@ -1242,10 +1305,22 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Skill Fishing base level requirements..." ); objmgr.LoadFishingBaseSkillLevel(); + sLog.outString( "Loading Achievements..." ); + sLog.outString(); + achievementmgr.LoadAchievementCriteriaList(); + achievementmgr.LoadRewards(); + achievementmgr.LoadRewardLocales(); + achievementmgr.LoadCompletedAchievements(); + sLog.outString( ">>> Achievements loaded" ); + sLog.outString(); + ///- Load dynamic data tables from the database sLog.outString( "Loading Auctions..." ); + sLog.outString(); objmgr.LoadAuctionItems(); objmgr.LoadAuctions(); + sLog.outString( ">>> Auctions loaded" ); + sLog.outString(); sLog.outString( "Loading Guilds..." ); objmgr.LoadGuilds(); @@ -1259,11 +1334,11 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading ReservedNames..." ); objmgr.LoadReservedPlayersNames(); - sLog.outString( "Loading GameObject for quests..." ); + sLog.outString( "Loading GameObjects for quests..." ); objmgr.LoadGameObjectForQuests(); sLog.outString( "Loading BattleMasters..." ); - objmgr.LoadBattleMastersEntry(); + sBattleGroundMgr.LoadBattleMastersEntry(); sLog.outString( "Loading GameTeleports..." ); objmgr.LoadGameTele(); @@ -1274,13 +1349,14 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading Npc Options..." ); objmgr.LoadNpcOptions(); - sLog.outString( "Loading vendors..." ); + sLog.outString( "Loading Vendors..." ); objmgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate - sLog.outString( "Loading trainers..." ); + sLog.outString( "Loading Trainers..." ); objmgr.LoadTrainerSpell(); // must be after load CreatureTemplate sLog.outString( "Loading Waypoints..." ); + sLog.outString(); WaypointMgr.Load(); sLog.outString( "Loading Creature Formations..." ); @@ -1295,12 +1371,15 @@ void World::SetInitialWorldSettings() ///- Load and initialize scripts sLog.outString( "Loading Scripts..." ); + sLog.outString(); objmgr.LoadQuestStartScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate objmgr.LoadQuestEndScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate objmgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data) objmgr.LoadGameObjectScripts(); // must be after load Creature/Gameobject(Template/Data) objmgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data) objmgr.LoadWaypointScripts(); + sLog.outString( ">>> Scripts loaded" ); + sLog.outString(); sLog.outString( "Loading Scripts text locales..." ); // must be after Load*Scripts calls objmgr.LoadDbScriptStrings(); @@ -1422,6 +1501,7 @@ void World::DetectDBCLang() m_defaultDbcLocale = LocaleConstant(default_locale); sLog.outString("Using %s DBC Locale as default. All available DBC locales: %s",localeNames[m_defaultDbcLocale],availableLocalsStr.empty() ? "<none>" : availableLocalsStr.c_str()); + sLog.outString(); } void World::RecordTimeDiff(const char *text, ...) @@ -1451,7 +1531,7 @@ void World::RecordTimeDiff(const char *text, ...) } /// Update the World ! -void World::Update(time_t diff) +void World::Update(uint32 diff) { m_updateTime = uint32(diff); if(m_configs[CONFIG_INTERVAL_LOG_UPDATE]) @@ -1505,13 +1585,13 @@ void World::Update(time_t diff) switch (i) { case 0: - AuctionMap = objmgr.GetAuctionsMap( 6 );//horde + AuctionMap = objmgr.GetAuctionsMap(AUCTION_HORDE); break; case 1: - AuctionMap = objmgr.GetAuctionsMap( 2 );//alliance + AuctionMap = objmgr.GetAuctionsMap(AUCTION_ALLIANCE); break; case 2: - AuctionMap = objmgr.GetAuctionsMap( 7 );//neutral + AuctionMap = objmgr.GetAuctionsMap(AUCTION_NEUTRAL); break; } @@ -1739,6 +1819,9 @@ void World::ScriptsProcess() case HIGHGUID_PET: source = HashMapHolder<Pet>::Find(step.sourceGUID); break; + case HIGHGUID_VEHICLE: + source = HashMapHolder<Vehicle>::Find(step.sourceGUID); + break; case HIGHGUID_PLAYER: source = HashMapHolder<Player>::Find(step.sourceGUID); break; @@ -1778,6 +1861,9 @@ void World::ScriptsProcess() case HIGHGUID_PET: target = HashMapHolder<Pet>::Find(step.targetGUID); break; + case HIGHGUID_VEHICLE: + target = HashMapHolder<Vehicle>::Find(step.targetGUID); + break; case HIGHGUID_PLAYER: // empty GUID case also target = HashMapHolder<Player>::Find(step.targetGUID); break; @@ -2008,8 +2094,8 @@ void World::ScriptsProcess() Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; - Trinity::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong); - Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(go,go_check); + MaNGOS::GameObjectWithDbGUIDCheck go_check(*summoner,step.script->datalong); + MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(summoner, go,go_check); TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker); CellLock<GridReadGuard> cell_lock(cell, p); @@ -2069,8 +2155,8 @@ void World::ScriptsProcess() Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; - Trinity::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong); - Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(door,go_check); + MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong); + MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check); TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker); CellLock<GridReadGuard> cell_lock(cell, p); @@ -2125,8 +2211,8 @@ void World::ScriptsProcess() Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; - Trinity::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong); - Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck> checker(door,go_check); + MaNGOS::GameObjectWithDbGUIDCheck go_check(*caster,step.script->datalong); + MaNGOS::GameObjectSearcher<MaNGOS::GameObjectWithDbGUIDCheck> checker(caster,door,go_check); TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectWithDbGUIDCheck>, GridTypeMapContainer > object_checker(checker); CellLock<GridReadGuard> cell_lock(cell, p); @@ -2342,7 +2428,7 @@ void World::ScriptsProcess() //sLog.outDebug("Attempting to find Creature: Db GUID: %i", step.script->datalong); Trinity::CreatureWithDbGUIDCheck target_check(((Unit*)source), step.script->datalong); - Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(target,target_check); + Trinity::CreatureSearcher<Trinity::CreatureWithDbGUIDCheck> checker(((Unit*)source), target, target_check); TypeContainerVisitor<Trinity::CreatureSearcher <Trinity::CreatureWithDbGUIDCheck>, GridTypeMapContainer > unit_checker(checker); CellLock<GridReadGuard> cell_lock(cell, p); @@ -2559,7 +2645,7 @@ void World::SendGMText(int32 string_id, ...) delete data_cache[i][j]; } -/// Send a System Message to all players (except self if mentioned) +/// DEPRICATED, only for debug purpose. Send a System Message to all players (except self if mentioned) void World::SendGlobalText(const char* text, WorldSession *self) { WorldPacket data; @@ -2850,7 +2936,7 @@ void World::SendServerMessage(uint32 type, const char *text, Player* player) SendGlobalMessage( &data ); } -void World::UpdateSessions( time_t diff ) +void World::UpdateSessions( uint32 diff ) { ///- Add new sessions while(!addSessQueue.empty()) diff --git a/src/game/World.h b/src/game/World.h index 502f403d130..8ceb356c076 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -103,9 +103,12 @@ enum WorldConfigs CONFIG_CHARACTERS_CREATING_DISABLED, CONFIG_CHARACTERS_PER_ACCOUNT, CONFIG_CHARACTERS_PER_REALM, + CONFIG_HEROIC_CHARACTERS_PER_REALM, + CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING, CONFIG_SKIP_CINEMATICS, CONFIG_MAX_PLAYER_LEVEL, CONFIG_START_PLAYER_LEVEL, + CONFIG_START_HEROIC_PLAYER_LEVEL, CONFIG_START_PLAYER_MONEY, CONFIG_MAX_HONOR_POINTS, CONFIG_START_HONOR_POINTS, @@ -122,12 +125,16 @@ enum WorldConfigs CONFIG_MAX_PRIMARY_TRADE_SKILL, CONFIG_MIN_PETITION_SIGNS, CONFIG_GM_LOGIN_STATE, + CONFIG_GM_VISIBLE_STATE, + CONFIG_GM_ACCEPT_TICKETS, CONFIG_GM_CHAT, CONFIG_GM_WISPERING_TO, CONFIG_GM_IN_GM_LIST, CONFIG_GM_IN_WHO_LIST, CONFIG_GM_LOG_TRADE, CONFIG_START_GM_LEVEL, + CONFIG_GM_LOWER_SECURITY, + CONFIG_GM_ALLOW_ACHIEVEMENT_GAINS, CONFIG_GROUP_VISIBILITY, CONFIG_MAIL_DELIVERY_DELAY, CONFIG_UPTIME_UPDATE, @@ -170,6 +177,8 @@ enum WorldConfigs CONFIG_DEATH_SICKNESS_LEVEL, CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP, CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE, + CONFIG_DEATH_BONES_WORLD, + CONFIG_DEATH_BONES_BG_OR_ARENA, CONFIG_THREAT_RADIUS, CONFIG_INSTANT_LOGOUT, CONFIG_DISABLE_BREATHING, @@ -182,8 +191,11 @@ enum WorldConfigs CONFIG_ARENA_RATING_DISCARD_TIMER, CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS, CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, + CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE, + CONFIG_ARENA_SEASON_ID, + CONFIG_ARENA_SEASON_IN_PROGRESS, CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, - + CONFIG_SKILL_MILLING, CONFIG_MAX_WHO, CONFIG_BG_START_MUSIC, CONFIG_START_ALL_SPELLS, @@ -211,6 +223,8 @@ enum Rates RATE_POWER_MANA, RATE_POWER_RAGE_INCOME, RATE_POWER_RAGE_LOSS, + RATE_POWER_RUNICPOWER_INCOME, + RATE_POWER_RUNICPOWER_LOSS, RATE_POWER_FOCUS, RATE_SKILL_DISCOVERY, RATE_DROP_ITEM_POOR, @@ -225,7 +239,6 @@ enum Rates RATE_XP_KILL, RATE_XP_QUEST, RATE_XP_EXPLORE, - RATE_XP_PAST_70, RATE_REPUTATION_GAIN, RATE_CREATURE_NORMAL_HP, RATE_CREATURE_ELITE_ELITE_HP, @@ -254,7 +267,6 @@ enum Rates RATE_MINING_AMOUNT, RATE_MINING_NEXT, RATE_TALENT, - RATE_LOYALTY, RATE_CORPSE_DECAY_LOOTED, RATE_INSTANCE_RESET_TIME, RATE_TARGET_POS_RECALCULATION_RANGE, @@ -450,9 +462,9 @@ class World static void StopNow(uint8 exitcode) { m_stopEvent = true; m_ExitCode = exitcode; } static bool IsStopped() { return m_stopEvent; } - void Update(time_t diff); + void Update(uint32 diff); - void UpdateSessions( time_t diff ); + void UpdateSessions( uint32 diff ); /// Set a server rate (see #Rates) void setRate(Rates rate,float value) { rate_values[rate]=value; } /// Get a server rate (see #Rates) diff --git a/src/game/WorldLog.cpp b/src/game/WorldLog.cpp index 4881b997495..eeac973ba5f 100644 --- a/src/game/WorldLog.cpp +++ b/src/game/WorldLog.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/WorldLog.h b/src/game/WorldLog.h index 8ec03d37d6d..47e1a912986 100644 --- a/src/game/WorldLog.h +++ b/src/game/WorldLog.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -51,9 +51,9 @@ class TRINITY_DLL_DECL WorldLog : public Trinity::Singleton<WorldLog, Trinity::C public: void Initialize(); /// Is the world logger active? - inline bool LogWorld(void) const { return (i_file != NULL); } + bool LogWorld(void) const { return (i_file != NULL); } /// %Log to the file - inline void Log(char const *fmt, ...) + void Log(char const *fmt, ...) { if( LogWorld() ) { diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index e043bbe9659..edcb0dc8a39 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -314,9 +314,9 @@ void WorldSession::LogoutPlayer(bool Save) _player->RepopAtGraveyard(); } - ///- Remove player from battleground (teleport to entrance) - if(_player->InBattleGround()) - _player->LeaveBattleground(); + ///- Teleport to home if the player is in an invalid instance + if(!_player->m_InstanceValid && !_player->isGameMaster()) + _player->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation()); sOutdoorPvPMgr.HandlePlayerLeaveZone(_player,_player->GetZoneId()); @@ -526,3 +526,93 @@ void WorldSession::SendAuthWaitQue(uint32 position) SendPacket(&packet); } } + +void WorldSession::LoadAccountData() +{ + for (uint32 i = 0; i < NUM_ACCOUNT_DATA_TYPES; ++i) + { + AccountData data; + m_accountData[i] = data; + } + + QueryResult *result = CharacterDatabase.PQuery("SELECT type, time, data FROM account_data WHERE account='%u'", GetAccountId()); + + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + + uint32 type = fields[0].GetUInt32(); + if(type < NUM_ACCOUNT_DATA_TYPES) + { + m_accountData[type].Time = fields[1].GetUInt32(); + m_accountData[type].Data = fields[2].GetCppString(); + } + } while (result->NextRow()); + + delete result; +} + +void WorldSession::SetAccountData(uint32 type, time_t time_, std::string data) +{ + m_accountData[type].Time = time_; + m_accountData[type].Data = data; + + uint32 acc = GetAccountId(); + + CharacterDatabase.BeginTransaction (); + CharacterDatabase.PExecute("DELETE FROM account_data WHERE account='%u' AND type='%u'", acc, type); + CharacterDatabase.escape_string(data); + CharacterDatabase.PExecute("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)time_, data.c_str()); + CharacterDatabase.CommitTransaction (); +} + +void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo *mi) +{ + CHECK_PACKET_SIZE(data, data.rpos()+4+2+4+4+4+4+4); + data >> mi->flags; + data >> mi->unk1; + data >> mi->time; + data >> mi->x; + data >> mi->y; + data >> mi->z; + data >> mi->o; + + if(mi->flags & MOVEMENTFLAG_ONTRANSPORT) + { + CHECK_PACKET_SIZE(data, data.rpos()+8+4+4+4+4+4+1); + data >> mi->t_guid; + data >> mi->t_x; + data >> mi->t_y; + data >> mi->t_z; + data >> mi->t_o; + data >> mi->t_time; + data >> mi->t_seat; + } + + if((mi->flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) || (mi->unk1 & 0x20)) + { + CHECK_PACKET_SIZE(data, data.rpos()+4); + data >> mi->s_pitch; + } + + CHECK_PACKET_SIZE(data, data.rpos()+4); + data >> mi->fallTime; + + if(mi->flags & MOVEMENTFLAG_JUMPING) + { + CHECK_PACKET_SIZE(data, data.rpos()+4+4+4+4); + data >> mi->j_unk; + data >> mi->j_sinAngle; + data >> mi->j_cosAngle; + data >> mi->j_xyspeed; + } + + if(mi->flags & MOVEMENTFLAG_SPLINE) + { + CHECK_PACKET_SIZE(data, data.rpos()+4); + data >> mi->u_unk1; + } +} diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index a19e0bb7376..f845fc0d1c9 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ #define __WORLDSESSION_H #include "Common.h" +#include "SharedDefines.h" class MailItemsInfo; struct ItemPrototype; @@ -47,6 +48,16 @@ class CharacterHandler; #define CHECK_PACKET_SIZE(P,S) if((P).size() < (S)) return SizeError((P),(S)); +#define NUM_ACCOUNT_DATA_TYPES 8 + +struct AccountData +{ + AccountData() : Time(0), Data("") {} + + time_t Time; + std::string Data; +}; + enum PartyOperation { PARTY_OP_INVITE = 0, @@ -81,6 +92,8 @@ class TRINITY_DLL_SPEC WorldSession void SizeError(WorldPacket const& packet, uint32 size) const; + void ReadMovementInfo(WorldPacket &data, MovementInfo *mi); + void SendPacket(WorldPacket const* packet); void SendNotification(const char *format,...) ATTR_PRINTF(2,3); void SendNotification(int32 string_id,...); @@ -141,7 +154,7 @@ class TRINITY_DLL_SPEC WorldSession void SendAttackStop(Unit const* enemy); - void SendBattlegGroundList( uint64 guid, uint32 bgTypeId ); + void SendBattlegGroundList( uint64 guid, BattleGroundTypeId bgTypeId ); void SendTradeStatus(uint32 status); void SendCancelTrade(); @@ -153,6 +166,11 @@ class TRINITY_DLL_SPEC WorldSession //pet void SendPetNameQuery(uint64 guid, uint32 petnumber); + // Account Data + AccountData *GetAccountData(uint32 type) { return &m_accountData[type]; } + void SetAccountData(uint32 type, time_t time_, std::string data); + void LoadAccountData(); + //mail //used with item_page table bool SendItemInfo( uint32 itemid, WorldPacket data ); @@ -310,6 +328,7 @@ class TRINITY_DLL_SPEC WorldSession void HandleGameObjectUseOpcode(WorldPacket& recPacket); void HandleMeetingStoneInfo(WorldPacket& recPacket); + void HandleGameobjectReportUse(WorldPacket& recvPacket); void HandleNameQueryOpcode(WorldPacket& recvPacket); @@ -323,9 +342,10 @@ class TRINITY_DLL_SPEC WorldSession void HandleMoveWorldportAckOpcode(); // for server-side calls void HandleMovementOpcodes(WorldPacket& recvPacket); - void HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& movementInfo, uint32& MovementFlags); + //void HandlePossessedMovement(WorldPacket& recv_data, MovementInfo& movementInfo, uint32& MovementFlags); void HandleSetActiveMoverOpcode(WorldPacket &recv_data); - void HandleNotActiveMoverOpcode(WorldPacket &recv_data); + void HandleMoveNotActiveMover(WorldPacket &recv_data); + void HandleDismissControlledVehicle(WorldPacket &recv_data); void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data); void HandleRequestRaidInfoOpcode( WorldPacket & recv_data ); @@ -386,7 +406,7 @@ class TRINITY_DLL_SPEC WorldSession void HandleGuildSaveEmblemOpcode(WorldPacket& recvPacket); void HandleTaxiNodeStatusQueryOpcode(WorldPacket& recvPacket); - void HandleTaxiQueryAvailableNodesOpcode(WorldPacket& recvPacket); + void HandleTaxiQueryAvailableNodes(WorldPacket& recvPacket); void HandleActivateTaxiOpcode(WorldPacket& recvPacket); void HandleActivateTaxiFarOpcode(WorldPacket& recvPacket); void HandleTaxiNextDestinationOpcode(WorldPacket& recvPacket); @@ -430,6 +450,7 @@ class TRINITY_DLL_SPEC WorldSession void HandleAuctionRemoveItem( WorldPacket & recv_data ); void HandleAuctionListOwnerItems( WorldPacket & recv_data ); void HandleAuctionPlaceBid( WorldPacket & recv_data ); + void HandleAuctionListPendingSales( WorldPacket & recv_data ); void HandleGetMail( WorldPacket & recv_data ); void HandleSendMail( WorldPacket & recv_data ); @@ -545,6 +566,7 @@ class TRINITY_DLL_SPEC WorldSession void HandlePetUnlearnOpcode( WorldPacket& recvPacket ); void HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ); void HandlePetCastSpellOpcode( WorldPacket& recvPacket ); + void HandlePetLearnTalent( WorldPacket& recvPacket ); void HandleSetActionBar(WorldPacket& recv_data); @@ -581,10 +603,9 @@ class TRINITY_DLL_SPEC WorldSession void HandleLfmSetNoneOpcode(WorldPacket& recv_data); void HandleLfmSetOpcode(WorldPacket& recv_data); void HandleLfgSetCommentOpcode(WorldPacket& recv_data); - void HandleNewUnknownOpcode(WorldPacket& recv_data); void HandleChooseTitleOpcode(WorldPacket& recv_data); void HandleRealmStateRequestOpcode(WorldPacket& recv_data); - void HandleAllowMoveAckOpcode(WorldPacket& recv_data); + void HandleTimeSyncResp(WorldPacket& recv_data); void HandleWhoisOpcode(WorldPacket& recv_data); void HandleResetInstancesOpcode(WorldPacket& recv_data); @@ -630,6 +651,29 @@ class TRINITY_DLL_SPEC WorldSession void HandleGuildBankBuyTab(WorldPacket& recv_data); void HandleGuildBankTabText(WorldPacket& recv_data); void HandleGuildBankSetTabText(WorldPacket& recv_data); + + // Calendar + void HandleCalendarGetCalendar(WorldPacket& recv_data); + void HandleCalendarGetEvent(WorldPacket& recv_data); + void HandleCalendarGuildFilter(WorldPacket& recv_data); + void HandleCalendarArenaTeam(WorldPacket& recv_data); + void HandleCalendarAddEvent(WorldPacket& recv_data); + void HandleCalendarUpdateEvent(WorldPacket& recv_data); + void HandleCalendarRemoveEvent(WorldPacket& recv_data); + void HandleCalendarCopyEvent(WorldPacket& recv_data); + void HandleCalendarEventInvite(WorldPacket& recv_data); + void HandleCalendarEventRsvp(WorldPacket& recv_data); + void HandleCalendarEventRemoveInvite(WorldPacket& recv_data); + void HandleCalendarEventStatus(WorldPacket& recv_data); + void HandleCalendarEventModeratorStatus(WorldPacket& recv_data); + void HandleCalendarComplain(WorldPacket& recv_data); + void HandleCalendarGetNumPending(WorldPacket& recv_data); + + void HandleSpellClick(WorldPacket& recv_data); + void HandleAlterAppearance(WorldPacket& recv_data); + void HandleRemoveGlyph(WorldPacket& recv_data); + void HandleCharCustomize(WorldPacket& recv_data); + void HandleInspectAchievements(WorldPacket& recv_data); private: // private trade methods void moveItems(Item* myItems[], Item* hisItems[]); @@ -652,6 +696,7 @@ class TRINITY_DLL_SPEC WorldSession LocaleConstant m_sessionDbcLocale; int m_sessionDbLocaleIndex; uint32 m_latency; + AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES]; ZThread::LockedQueue<WorldPacket*,ZThread::FastMutex> _recvQueue; }; diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index c54a7aaf45a..9913c912c70 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -1,7 +1,7 @@ /* -* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * -* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -54,8 +54,37 @@ struct ServerPktHeader { - uint16 size; - uint16 cmd; + /** + * size is the length of the payload _plus_ the length of the opcode + */ + ServerPktHeader(uint32 size, uint16 cmd) : size(size) + { + uint8 headerIndex=0; + if(isLargePacket()) + { + sLog.outDebug("initializing large server to client packet. Size: %u, cmd: %u", size, cmd); + header[headerIndex++] = 0x80|(0xFF &(size>>16)); + } + header[headerIndex++] = 0xFF &(size>>8); + header[headerIndex++] = 0xFF &size; + + header[headerIndex++] = 0xFF & cmd; + header[headerIndex++] = 0xFF & (cmd>>8); + } + + uint8 getHeaderLength() + { + // cmd = 2 bytes, size= 2||3bytes + return 2+(isLargePacket()?3:2); + } + + bool isLargePacket() + { + return size > 0x7FFF; + } + + const uint32 size; + uint8 header[5]; }; struct ClientPktHeader @@ -84,6 +113,9 @@ m_OverSpeedPings (0), m_LastPingTime (ACE_Time_Value::zero) { reference_counting_policy ().value (ACE_Event_Handler::Reference_Counting_Policy::ENABLED); + + msg_queue()->high_water_mark(8*1024*1024); + msg_queue()->low_water_mark(8*1024*1024); } WorldSocket::~WorldSocket (void) @@ -97,10 +129,6 @@ WorldSocket::~WorldSocket (void) closing_ = true; peer ().close (); - - WorldPacket* pct; - while (m_PacketQueue.dequeue_head (pct) == 0) - delete pct; } bool WorldSocket::IsClosed (void) const @@ -160,18 +188,35 @@ int WorldSocket::SendPacket (const WorldPacket& pct) sWorldLog.Log ("\n\n"); } - if (iSendPacket (pct) == -1) + ServerPktHeader header(pct.size()+2, pct.GetOpcode()); + m_Crypt.EncryptSend ( header.header, header.getHeaderLength()); + + if (m_OutBuffer->space () >= pct.size () + header.getHeaderLength() && msg_queue()->is_empty()) + { + // Put the packet on the buffer. + if (m_OutBuffer->copy ((char*) header.header, header.getHeaderLength()) == -1) + ACE_ASSERT (false); + + if (!pct.empty ()) + if (m_OutBuffer->copy ((char*) pct.contents (), pct.size ()) == -1) + ACE_ASSERT (false); + } + else { - WorldPacket* npct; + // Enqueue the packet. + ACE_Message_Block* mb; + + ACE_NEW_RETURN(mb, ACE_Message_Block(pct.size () + header.getHeaderLength()), -1); + + mb->copy((char*) header.header, header.getHeaderLength()); - ACE_NEW_RETURN (npct, WorldPacket (pct), -1); + if (!pct.empty ()) + mb->copy((const char*)pct.contents(), pct.size ()); - // NOTE maybe check of the size of the queue can be good ? - // to make it bounded instead of unbounded - if (m_PacketQueue.enqueue_tail (npct) == -1) + if(msg_queue()->enqueue_tail(mb,(ACE_Time_Value*)&ACE_Time_Value::zero) == -1) { - delete npct; - sLog.outError ("WorldSocket::SendPacket: m_PacketQueue.enqueue_tail failed"); + sLog.outError("WorldSocket::SendPacket enqueue_tail"); + mb->release(); return -1; } } @@ -296,7 +341,7 @@ int WorldSocket::handle_output (ACE_HANDLE) const size_t send_len = m_OutBuffer->length (); if (send_len == 0) - return cancel_wakeup_output (Guard); + return handle_output_queue (Guard); #ifdef MSG_NOSIGNAL ssize_t n = peer ().send (m_OutBuffer->rd_ptr (), send_len, MSG_NOSIGNAL); @@ -326,15 +371,73 @@ int WorldSocket::handle_output (ACE_HANDLE) { m_OutBuffer->reset (); - if (!iFlushPacketQueue ()) - return cancel_wakeup_output (Guard); - else - return schedule_wakeup_output (Guard); + return handle_output_queue (Guard); } ACE_NOTREACHED (return 0); } +int WorldSocket::handle_output_queue (GuardType& g) +{ + if(msg_queue()->is_empty()) + return cancel_wakeup_output(g); + + ACE_Message_Block *mblk; + + if(msg_queue()->dequeue_head(mblk, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1) + { + sLog.outError("WorldSocket::handle_output_queue dequeue_head"); + return -1; + } + + const size_t send_len = mblk->length (); + +#ifdef MSG_NOSIGNAL + ssize_t n = peer ().send (mblk->rd_ptr (), send_len, MSG_NOSIGNAL); +#else + ssize_t n = peer ().send (mblk->rd_ptr (), send_len); +#endif // MSG_NOSIGNAL + + if (n == 0) + { + mblk->release(); + + return -1; + } + else if (n == -1) + { + if (errno == EWOULDBLOCK || errno == EAGAIN) + { + msg_queue()->enqueue_head(mblk, (ACE_Time_Value*) &ACE_Time_Value::zero); + return schedule_wakeup_output (g); + } + + mblk->release(); + return -1; + } + else if (n < send_len) //now n > 0 + { + mblk->rd_ptr (static_cast<size_t> (n)); + + if (msg_queue()->enqueue_head(mblk, (ACE_Time_Value*) &ACE_Time_Value::zero) == -1) + { + sLog.outError("WorldSocket::handle_output_queue enqueue_head"); + mblk->release(); + return -1; + } + + return schedule_wakeup_output (g); + } + else //now n == send_len + { + mblk->release(); + + return msg_queue()->is_empty() ? cancel_wakeup_output(g) : ACE_Event_Handler::WRITE_MASK; + } + + ACE_NOTREACHED(return -1); +} + int WorldSocket::handle_close (ACE_HANDLE h, ACE_Reactor_Mask) { // Critical section @@ -362,10 +465,15 @@ int WorldSocket::Update (void) if (closing_) return -1; - if (m_OutActive || m_OutBuffer->length () == 0) + if (m_OutActive || (m_OutBuffer->length () == 0 && msg_queue()->is_empty())) return 0; - return handle_output (get_handle ()); + int ret; + do + ret = handle_output (get_handle ()); + while( ret > 0 ); + + return ret; } int WorldSocket::handle_input_header (void) @@ -639,7 +747,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) // NOTE: ATM the socket is singlethread, have this in mind ... uint8 digest[20]; uint32 clientSeed; - uint32 unk2; + uint32 unk2, unk3; uint32 BuiltNumberClient; uint32 id, security; //uint8 expansion = 0; @@ -661,6 +769,7 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) recvPacket >> BuiltNumberClient; // for now no use recvPacket >> unk2; recvPacket >> account; + recvPacket >> unk3; if (recvPacket.size () < (4 + 4 + (account.size () + 1) + 4 + 20)) { @@ -684,17 +793,17 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) QueryResult *result = LoginDatabase.PQuery ("SELECT " - "id, " //0 - "gmlevel, " //1 - "sessionkey, " //2 - "last_ip, " //3 - "locked, " //4 - "sha_pass_hash, " //5 - "v, " //6 - "s, " //7 - "expansion, " //8 - "mutetime, " //9 - "locale " //10 + "id, " //0 + "gmlevel, " //1 + "sessionkey, " //2 + "last_ip, " //3 + "locked, " //4 + "sha_pass_hash, " //5 + "v, " //6 + "s, " //7 + "expansion, " //8 + "mutetime, " //9 + "locale " //10 "FROM account " "WHERE username = '%s'", safe_account.c_str ()); @@ -788,6 +897,9 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) id = fields[0].GetUInt32 (); security = fields[1].GetUInt16 (); + if(security > SEC_ADMINISTRATOR) // prevent invalid security settings in DB + security = SEC_ADMINISTRATOR; + K.SetHexStr (fields[2].GetString ()); time_t mutetime = time_t (fields[9].GetUInt64 ()); @@ -880,6 +992,8 @@ int WorldSocket::HandleAuthSession (WorldPacket& recvPacket) m_Crypt.SetKey (&K); m_Crypt.Init (); + m_Session->LoadAccountData(); + // In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec ACE_OS::sleep (ACE_Time_Value (0, 10000)); @@ -961,25 +1075,19 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket) return SendPacket (packet); } -int WorldSocket::iSendPacket (const WorldPacket& pct) +/*int WorldSocket::iSendPacket (const WorldPacket& pct) { - if (m_OutBuffer->space () < pct.size () + sizeof (ServerPktHeader)) + ServerPktHeader header(pct.size()+2, pct.GetOpcode()); + if (m_OutBuffer->space () < pct.size () + header.getHeaderLength()) { errno = ENOBUFS; return -1; } - ServerPktHeader header; - header.cmd = pct.GetOpcode (); - EndianConvert(header.cmd); + m_Crypt.EncryptSend ( header.header, header.getHeaderLength()); - header.size = (uint16) pct.size () + 2; - EndianConvertReverse(header.size); - - m_Crypt.EncryptSend ((uint8*) & header, sizeof (header)); - - if (m_OutBuffer->copy ((char*) & header, sizeof (header)) == -1) + if (m_OutBuffer->copy ((char*) header.header, header.getHeaderLength()) == -1) ACE_ASSERT (false); if (!pct.empty ()) @@ -1015,4 +1123,4 @@ bool WorldSocket::iFlushPacketQueue () } return haveone; -} +}*/ diff --git a/src/game/WorldSocket.h b/src/game/WorldSocket.h index fc564b6553a..15d3ec31e06 100644 --- a/src/game/WorldSocket.h +++ b/src/game/WorldSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -103,9 +103,6 @@ class WorldSocket : protected WorldHandler typedef ACE_Thread_Mutex LockType; typedef ACE_Guard<LockType> GuardType; - /// Queue for storing packets for which there is no space. - typedef ACE_Unbounded_Queue< WorldPacket* > PacketQueueT; - /// Check if socket is closed. bool IsClosed (void) const; @@ -161,6 +158,9 @@ class WorldSocket : protected WorldHandler int cancel_wakeup_output (GuardType& g); int schedule_wakeup_output (GuardType& g); + /// Drain the queue if its not empty. + int handle_output_queue (GuardType& g); + /// process one incoming packet. /// @param new_pct received packet ,note that you need to delete it. int ProcessIncoming (WorldPacket* new_pct); @@ -171,16 +171,6 @@ class WorldSocket : protected WorldHandler /// Called by ProcessIncoming() on CMSG_PING. int HandlePing (WorldPacket& recvPacket); - /// Try to write WorldPacket to m_OutBuffer ,return -1 if no space - /// Need to be called with m_OutBufferLock lock held - int iSendPacket (const WorldPacket& pct); - - /// Flush m_PacketQueue if there are packets in it - /// Need to be called with m_OutBufferLock lock held - /// @return true if it wrote to the buffer ( AKA you need - /// to mark the socket for output ). - bool iFlushPacketQueue (); - private: /// Time in which the last ping was received ACE_Time_Value m_LastPingTime; @@ -220,10 +210,6 @@ class WorldSocket : protected WorldHandler /// Size of the m_OutBuffer. size_t m_OutBufferSize; - /// Here are stored packets for which there was no space on m_OutBuffer, - /// this allows not-to kick player if its buffer is overflowed. - PacketQueueT m_PacketQueue; - /// True if the socket is registered with the reactor for output bool m_OutActive; diff --git a/src/game/WorldSocketMgr.cpp b/src/game/WorldSocketMgr.cpp index baf8896f3f2..b6ea361f7e3 100644 --- a/src/game/WorldSocketMgr.cpp +++ b/src/game/WorldSocketMgr.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 2005-2008,2007 MaNGOS <http://getmangos.com/> * -* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/game/WorldSocketMgr.h b/src/game/WorldSocketMgr.h index fc009d69f80..d7cb627b11c 100644 --- a/src/game/WorldSocketMgr.h +++ b/src/game/WorldSocketMgr.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/mangosd/CMakeLists.txt b/src/mangosd/CMakeLists.txt new file mode 100644 index 00000000000..dc5941ef4e2 --- /dev/null +++ b/src/mangosd/CMakeLists.txt @@ -0,0 +1,53 @@ + +########### next target ############### + +SET(trinity-core_SRCS +CliRunnable.cpp +CliRunnable.h +Main.cpp +Master.cpp +Master.h +RASocket.cpp +RASocket.h +WorldRunnable.cpp +WorldRunnable.h +) + +add_executable(trinity-core ${trinity-core_SRCS}) +add_definitions( +-D_TRINITY_CORE_CONFIG='"${CONF_DIR}/trinitycore.conf"' +) +IF (DO_MYSQL) + SET_TARGET_PROPERTIES(trinity-core PROPERTIES LINK_FLAGS "-pthread") +ENDIF(DO_MYSQL) + + + +target_link_libraries( +trinity-core +game +shared +zlib +trinityframework +trinitysockets +trinitydatabase +trinityauth +trinityconfig +vmaps +ZThread +g3dlite +${SCRIPT_LIB} +${MYSQL_LIBRARIES} +${POSTGRE_LIBS} +${SSLLIB} +${ACE_LIBRARY} +${ZLIB} +) + +install(TARGETS trinity-core DESTINATION bin) + + +########### install files ############### + +install(FILES mangosd.conf.dist.in DESTINATION etc) + diff --git a/src/mangosd/CliRunnable.cpp b/src/mangosd/CliRunnable.cpp new file mode 100644 index 00000000000..f3bc640f9ff --- /dev/null +++ b/src/mangosd/CliRunnable.cpp @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup Trinityd +/// @{ +/// \file + +#include "Common.h" +#include "Language.h" +#include "Log.h" +#include "World.h" +#include "ScriptCalls.h" +#include "ObjectMgr.h" +#include "WorldSession.h" +#include "Config/ConfigEnv.h" +#include "Util.h" +#include "AccountMgr.h" +#include "CliRunnable.h" +#include "MapManager.h" +#include "Player.h" +#include "Chat.h" + +void utf8print(const char* str) +{ +#if PLATFORM == PLATFORM_WINDOWS + wchar_t wtemp_buf[6000]; + size_t wtemp_len = 6000-1; + if(!Utf8toWStr(str,strlen(str),wtemp_buf,wtemp_len)) + return; + + char temp_buf[6000]; + CharToOemBuffW(&wtemp_buf[0],&temp_buf[0],wtemp_len+1); + printf(temp_buf); +#else + printf(str); +#endif +} + +/// Delete a user account and all associated characters in this realm +/// \todo This function has to be enhanced to respect the login/realm split (delete char, delete account chars in realm, delete account chars in realm then delete account +bool ChatHandler::HandleAccountDeleteCommand(const char* args) +{ + if(!*args) + return false; + + ///- Get the account name from the command line + char *account_name_str=strtok ((char*)args," "); + if (!account_name_str) + return false; + + std::string account_name = account_name_str; + if(!AccountMgr::normilizeString(account_name)) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + uint32 account_id = accmgr.GetId(account_name); + if(!account_id) + { + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + /// Commands not recommended call from chat, but support anyway + /// can delete only for account with less security + /// This is also reject self apply in fact + if(HasLowerSecurityAccount (NULL,account_id,true)) + return false; + + AccountOpResult result = accmgr.DeleteAccount(account_id); + switch(result) + { + case AOR_OK: + PSendSysMessage(LANG_ACCOUNT_DELETED,account_name.c_str()); + break; + case AOR_NAME_NOT_EXIST: + PSendSysMessage(LANG_ACCOUNT_NOT_EXIST,account_name.c_str()); + SetSentErrorMessage(true); + return false; + case AOR_DB_INTERNAL_ERROR: + PSendSysMessage(LANG_ACCOUNT_NOT_DELETED_SQL_ERROR,account_name.c_str()); + SetSentErrorMessage(true); + return false; + default: + PSendSysMessage(LANG_ACCOUNT_NOT_DELETED,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +bool ChatHandler::HandleCharacterDeleteCommand(const char* args) +{ + if(!*args) + return false; + + char *character_name_str = strtok((char*)args," "); + if(!character_name_str) + return false; + + std::string character_name = character_name_str; + if(!normalizePlayerName(character_name)) + return false; + + uint64 character_guid; + uint32 account_id; + + Player *player = objmgr.GetPlayer(character_name.c_str()); + if(player) + { + character_guid = player->GetGUID(); + account_id = player->GetSession()->GetAccountId(); + player->GetSession()->KickPlayer(); + } + else + { + character_guid = objmgr.GetPlayerGUIDByName(character_name); + if(!character_guid) + { + PSendSysMessage(LANG_NO_PLAYER,character_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + account_id = objmgr.GetPlayerAccountIdByGUID(character_guid); + } + + std::string account_name; + accmgr.GetName (account_id,account_name); + + Player::DeleteFromDB(character_guid, account_id, true); + PSendSysMessage(LANG_CHARACTER_DELETED,character_name.c_str(),GUID_LOPART(character_guid),account_name.c_str(), account_id); + return true; +} + +/// Exit the realm +bool ChatHandler::HandleServerExitCommand(const char* args) +{ + SendSysMessage(LANG_COMMAND_EXIT); + World::StopNow(SHUTDOWN_EXIT_CODE); + return true; +} + +/// Display info on users currently in the realm +bool ChatHandler::HandleAccountOnlineListCommand(const char* args) +{ + ///- Get the list of accounts ID logged to the realm + QueryResult *resultDB = CharacterDatabase.Query("SELECT name,account FROM characters WHERE online > 0"); + if (!resultDB) + return true; + + ///- Display the list of account/characters online + SendSysMessage("====================================================================="); + SendSysMessage(LANG_ACCOUNT_LIST_HEADER); + SendSysMessage("====================================================================="); + + ///- Circle through accounts + do + { + Field *fieldsDB = resultDB->Fetch(); + std::string name = fieldsDB[0].GetCppString(); + uint32 account = fieldsDB[1].GetUInt32(); + + ///- Get the username, last IP and GM level of each account + // No SQL injection. account is uint32. + // 0 1 2 3 + QueryResult *resultLogin = LoginDatabase.PQuery("SELECT username, last_ip, gmlevel, expansion FROM account WHERE id = '%u'",account); + + if(resultLogin) + { + Field *fieldsLogin = resultLogin->Fetch(); + PSendSysMessage("|%15s| %20s | %15s |%4d|%5d|", + fieldsLogin[0].GetString(),name.c_str(),fieldsLogin[1].GetString(),fieldsLogin[2].GetUInt32(),fieldsLogin[3].GetUInt32()); + + delete resultLogin; + } + else + PSendSysMessage(LANG_ACCOUNT_LIST_ERROR,name.c_str()); + + }while(resultDB->NextRow()); + + delete resultDB; + + SendSysMessage("====================================================================="); + return true; +} + +/// Create an account +bool ChatHandler::HandleAccountCreateCommand(const char* args) +{ + if(!*args) + return false; + + ///- %Parse the command line arguments + char *szAcc = strtok((char*)args, " "); + char *szPassword = strtok(NULL, " "); + if(!szAcc || !szPassword) + return false; + + // normilized in accmgr.CreateAccount + std::string account_name = szAcc; + std::string password = szPassword; + + AccountOpResult result = accmgr.CreateAccount(account_name, password); + switch(result) + { + case AOR_OK: + PSendSysMessage(LANG_ACCOUNT_CREATED,account_name.c_str()); + break; + case AOR_NAME_TOO_LONG: + SendSysMessage(LANG_ACCOUNT_TOO_LONG); + SetSentErrorMessage(true); + return false; + case AOR_NAME_ALREDY_EXIST: + SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST); + SetSentErrorMessage(true); + return false; + case AOR_DB_INTERNAL_ERROR: + PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR,account_name.c_str()); + SetSentErrorMessage(true); + return false; + default: + PSendSysMessage(LANG_ACCOUNT_NOT_CREATED,account_name.c_str()); + SetSentErrorMessage(true); + return false; + } + + return true; +} + +/// Set the level of logging +bool ChatHandler::HandleServerSetLogLevelCommand(const char *args) +{ + if(!*args) + return false; + + char *NewLevel = strtok((char*)args, " "); + if (!NewLevel) + return false; + + sLog.SetLogLevel(NewLevel); + return true; +} + +/// set diff time record interval +bool ChatHandler::HandleServerSetDiffTimeCommand(const char *args) +{ + if(!*args) + return false; + + char *NewTimeStr = strtok((char*)args, " "); + if(!NewTimeStr) + return false; + + int32 NewTime =atoi(NewTimeStr); + if(NewTime < 0) + return false; + + sWorld.SetRecordDiffInterval(NewTime); + printf( "Record diff every %u ms\n", NewTime); + return true; +} + + +/// @} + +#ifdef linux +// Non-blocking keypress detector, when return pressed, return 1, else always return 0 +int kb_hit_return() +{ + struct timeval tv; + fd_set fds; + tv.tv_sec = 0; + tv.tv_usec = 0; + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); + return FD_ISSET(STDIN_FILENO, &fds); +} +#endif + +/// %Thread start +void CliRunnable::run() +{ + ///- Init new SQL thread for the world database (one connection call enough) + WorldDatabase.ThreadStart(); // let thread do safe mySQL requests + + char commandbuf[256]; + + ///- Display the list of available CLI functions then beep + sLog.outString(); + + if(sConfig.GetBoolDefault("BeepAtStart", true)) + printf("\a"); // \a = Alert + + // print this here the first time + // later it will be printed after command queue updates + printf("TC>"); + + ///- As long as the World is running (no World::m_stopEvent), get the command line and handle it + while (!World::IsStopped()) + { + fflush(stdout); + #ifdef linux + while (!kb_hit_return() && !World::IsStopped()) + // With this, we limit CLI to 10commands/second + usleep(100); + if (World::IsStopped()) + break; + #endif + char *command_str = fgets(commandbuf,sizeof(commandbuf),stdin); + if (command_str != NULL) + { + for(int x=0;command_str[x];x++) + if(command_str[x]=='\r'||command_str[x]=='\n') + { + command_str[x]=0; + break; + } + + + if(!*command_str) + { + printf("TC>"); + continue; + } + + std::string command; + if(!consoleToUtf8(command_str,command)) // convert from console encoding to utf8 + { + printf("TC>"); + continue; + } + + sWorld.QueueCliCommand(&utf8print,command.c_str()); + } + else if (feof(stdin)) + { + World::StopNow(SHUTDOWN_EXIT_CODE); + } + } + + ///- End the database thread + WorldDatabase.ThreadEnd(); // free mySQL thread resources +} diff --git a/src/mangosd/CliRunnable.h b/src/mangosd/CliRunnable.h new file mode 100644 index 00000000000..e5f78bb5259 --- /dev/null +++ b/src/mangosd/CliRunnable.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup Trinityd +/// @{ +/// \file + +#ifndef __CLIRUNNABLE_H +#define __CLIRUNNABLE_H + +/// Command Line Interface handling thread +class CliRunnable : public ZThread::Runnable +{ + public: + void run(); +}; +#endif +/// @} diff --git a/src/mangosd/Main.cpp b/src/mangosd/Main.cpp new file mode 100644 index 00000000000..68c467d6265 --- /dev/null +++ b/src/mangosd/Main.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup Trinityd Trinity Daemon +/// @{ +/// \file + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Config/ConfigEnv.h" +#include "Log.h" +#include "Master.h" + +#ifndef _TRINITY_CORE_CONFIG +# define _TRINITY_CORE_CONFIG "TrinityCore.conf" +#endif //_TRINITY_CORE_CONFIG + +// Format is YYYYMMDDRR where RR is the change in the conf file +// for that day. +#ifndef _TRINITY_CORE_CONFVER +# define _TRINITY_CORE_CONFVER 2008022901 +#endif //_TRINITY_CORE_CONFVER + +#ifdef WIN32 +#include "ServiceWin32.h" +char serviceName[] = "TrinityCore"; +char serviceLongName[] = "Trinity core service"; +char serviceDescription[] = "Massive Network Game Object Server"; +/* + * -1 - not in service mode + * 0 - stopped + * 1 - running + * 2 - paused + */ +int m_ServiceStatus = -1; +#endif + +DatabaseType WorldDatabase; ///< Accessor to the world database +DatabaseType CharacterDatabase; ///< Accessor to the character database +DatabaseType LoginDatabase; ///< Accessor to the realm/login database + +uint32 realmID; ///< Id of the realm + +/// Print out the usage string for this program on the console. +void usage(const char *prog) +{ + sLog.outString("Usage: \n %s [<options>]\n" + " -c config_file use config_file as configuration file\n\r" + #ifdef WIN32 + " Running as service functions:\n\r" + " --service run as service\n\r" + " -s install install service\n\r" + " -s uninstall uninstall service\n\r" + #endif + ,prog); +} + +/// Launch the Trinity server +extern int main(int argc, char **argv) +{ + ///- Command line parsing to get the configuration file name + char const* cfg_file = _TRINITY_CORE_CONFIG; + int c=1; + while( c < argc ) + { + if( strcmp(argv[c],"-c") == 0) + { + if( ++c >= argc ) + { + sLog.outError("Runtime-Error: -c option requires an input argument"); + usage(argv[0]); + return 1; + } + else + cfg_file = argv[c]; + } + + #ifdef WIN32 + //////////// + //Services// + //////////// + if( strcmp(argv[c],"-s") == 0) + { + if( ++c >= argc ) + { + sLog.outError("Runtime-Error: -s option requires an input argument"); + usage(argv[0]); + return 1; + } + if( strcmp(argv[c],"install") == 0) + { + if (WinServiceInstall()) + sLog.outString("Installing service"); + return 1; + } + else if( strcmp(argv[c],"uninstall") == 0) + { + if(WinServiceUninstall()) + sLog.outString("Uninstalling service"); + return 1; + } + else + { + sLog.outError("Runtime-Error: unsupported option %s",argv[c]); + usage(argv[0]); + return 1; + } + } + if( strcmp(argv[c],"--service") == 0) + { + WinServiceRun(); + } + //// + #endif + ++c; + } + + if (!sConfig.SetSource(cfg_file)) + { + sLog.outError("Could not find configuration file %s.", cfg_file); + return 1; + } + sLog.outString("Using configuration file %s.", cfg_file); + + uint32 confVersion = sConfig.GetIntDefault("ConfVersion", 0); + if (confVersion < _TRINITY_CORE_CONFVER) + { + sLog.outError("*****************************************************************************"); + sLog.outError(" WARNING: Your trinitycore.conf version indicates your conf file is out of date!"); + sLog.outError(" Please check for updates, as your current default values may cause"); + sLog.outError(" strange behavior."); + sLog.outError("*****************************************************************************"); + clock_t pause = 3000 + clock(); + + while (pause > clock()) {} + } + + ///- and run the 'Master' + /// \todo Why do we need this 'Master'? Can't all of this be in the Main as for Realmd? + return sMaster.Run(); + + // at sMaster return function exist with codes + // 0 - normal shutdown + // 1 - shutdown at error + // 2 - restart command used, this code can be used by restarter for restart Trinityd +} + +/// @} diff --git a/src/mangosd/Makefile.am b/src/mangosd/Makefile.am new file mode 100644 index 00000000000..7e1cd086d3c --- /dev/null +++ b/src/mangosd/Makefile.am @@ -0,0 +1,62 @@ +# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> +# +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = $(TRINI_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir)/../../dep/include -I$(srcdir)/../framework -I$(srcdir)/../shared -I$(srcdir)/../game -I$(srcdir) -DSYSCONFDIR=\"$(sysconfdir)/\" + +## Build world list daemon as standalone program +bin_PROGRAMS = trinity-worldd +trinity_worldd_SOURCES = \ + CliRunnable.cpp \ + CliRunnable.h \ + Main.cpp \ + Master.cpp \ + Master.h \ + RASocket.cpp \ + RASocket.h \ + WorldRunnable.cpp \ + WorldRunnable.h + +## Link world daemon against the shared library +trinity_worldd_LDADD = ../bindings/scripts/libtrinityscript.la ../game/libmangosgame.a ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../shared/vmap/libmangosvmaps.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la ../../dep/src/g3dlite/libg3dlite.a +trinity_worldd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L../../dep/src/g3dlite -L../bindings/scripts/ -L$(libdir) $(TRINI_LIBS) -export-dynamic + +## Additional files to include when running 'make dist' +# Include world daemon configuration +EXTRA_DIST = \ + mangosd.conf.dist + +## Additional files to install +sysconf_DATA = \ + mangosd.conf.dist + +install-data-hook: + @list='$(sysconf_DATA)'; for p in $$list; do \ + dest=`echo $$p | sed -e s/.dist//`; \ + if test -f $(DESTDIR)$(sysconfdir)/$$dest; then \ + echo "$@ will not overwrite existing $(DESTDIR)$(sysconfdir)/$$dest"; \ + else \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest; \ + fi; \ + done + +clean-local: + rm -f $(sysconf_DATA) diff --git a/src/mangosd/Master.cpp b/src/mangosd/Master.cpp new file mode 100644 index 00000000000..f175d4d82b0 --- /dev/null +++ b/src/mangosd/Master.cpp @@ -0,0 +1,519 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup Trinityd +*/ + +#include <ace/OS_NS_signal.h> + +#include "WorldSocketMgr.h" +#include "Common.h" +#include "Master.h" +#include "WorldSocket.h" +#include "WorldRunnable.h" +#include "World.h" +#include "Log.h" +#include "Timer.h" +#include "Policies/SingletonImp.h" +#include "SystemConfig.h" +#include "Config/ConfigEnv.h" +#include "Database/DatabaseEnv.h" +#include "CliRunnable.h" +#include "RASocket.h" +#include "ScriptCalls.h" +#include "Util.h" + +#include "sockets/TcpSocket.h" +#include "sockets/Utility.h" +#include "sockets/Parse.h" +#include "sockets/Socket.h" +#include "sockets/SocketHandler.h" +#include "sockets/ListenSocket.h" + +#ifdef WIN32 +#include "ServiceWin32.h" +extern int m_ServiceStatus; +#endif + +/// \todo Warning disabling not useful under VC++2005. Can somebody say on which compiler it is useful? +#pragma warning(disable:4305) + +INSTANTIATE_SINGLETON_1( Master ); + +volatile uint32 Master::m_masterLoopCounter = 0; + +class FreezeDetectorRunnable : public ZThread::Runnable +{ +public: + FreezeDetectorRunnable() { _delaytime = 0; } + uint32 m_loops, m_lastchange; + uint32 w_loops, w_lastchange; + uint32 _delaytime; + void SetDelayTime(uint32 t) { _delaytime = t; } + void run(void) + { + if(!_delaytime) + return; + sLog.outString("Starting up anti-freeze thread (%u seconds max stuck time)...",_delaytime/1000); + m_loops = 0; + w_loops = 0; + m_lastchange = 0; + w_lastchange = 0; + while(!World::IsStopped()) + { + ZThread::Thread::sleep(1000); + uint32 curtime = getMSTime(); + //DEBUG_LOG("anti-freeze: time=%u, counters=[%u; %u]",curtime,Master::m_masterLoopCounter,World::m_worldLoopCounter); + + // There is no Master anymore + // TODO: clear the rest of the code +// // normal work +// if(m_loops != Master::m_masterLoopCounter) +// { +// m_lastchange = curtime; +// m_loops = Master::m_masterLoopCounter; +// } +// // possible freeze +// else if(getMSTimeDiff(m_lastchange,curtime) > _delaytime) +// { +// sLog.outError("Main/Sockets Thread hangs, kicking out server!"); +// *((uint32 volatile*)NULL) = 0; // bang crash +// } + + // normal work + if(w_loops != World::m_worldLoopCounter) + { + w_lastchange = curtime; + w_loops = World::m_worldLoopCounter; + } + // possible freeze + else if(getMSTimeDiff(w_lastchange,curtime) > _delaytime) + { + sLog.outError("World Thread hangs, kicking out server!"); + *((uint32 volatile*)NULL) = 0; // bang crash + } + } + sLog.outString("Anti-freeze thread exiting without problems."); + } +}; + +class RARunnable : public ZThread::Runnable +{ +public: + uint32 numLoops, loopCounter; + + RARunnable () + { + uint32 socketSelecttime = sWorld.getConfig (CONFIG_SOCKET_SELECTTIME); + numLoops = (sConfig.GetIntDefault ("MaxPingTime", 30) * (MINUTE * 1000000 / socketSelecttime)); + loopCounter = 0; + } + + void + checkping () + { + // ping if need + if ((++loopCounter) == numLoops) + { + loopCounter = 0; + sLog.outDetail ("Ping MySQL to keep connection alive"); + delete WorldDatabase.Query ("SELECT 1 FROM command LIMIT 1"); + delete LoginDatabase.Query ("SELECT 1 FROM realmlist LIMIT 1"); + delete CharacterDatabase.Query ("SELECT 1 FROM bugreport LIMIT 1"); + } + } + + void + run (void) + { + SocketHandler h; + + // Launch the RA listener socket + ListenSocket<RASocket> RAListenSocket (h); + bool usera = sConfig.GetBoolDefault ("Ra.Enable", false); + + if (usera) + { + port_t raport = sConfig.GetIntDefault ("Ra.Port", 3443); + std::string stringip = sConfig.GetStringDefault ("Ra.IP", "0.0.0.0"); + ipaddr_t raip; + if (!Utility::u2ip (stringip, raip)) + sLog.outError ("Trinity RA can not bind to ip %s", stringip.c_str ()); + else if (RAListenSocket.Bind (raip, raport)) + sLog.outError ("Trinity RA can not bind to port %d on %s", raport, stringip.c_str ()); + else + { + h.Add (&RAListenSocket); + + sLog.outString ("Starting Remote access listner on port %d on %s", raport, stringip.c_str ()); + } + } + + // Socket Selet time is in microseconds , not miliseconds!! + uint32 socketSelecttime = sWorld.getConfig (CONFIG_SOCKET_SELECTTIME); + + // if use ra spend time waiting for io, if not use ra ,just sleep + if (usera) + while (!World::IsStopped()) + { + h.Select (0, socketSelecttime); + checkping (); + } + else + while (!World::IsStopped()) + { + ZThread::Thread::sleep (static_cast<unsigned long> (socketSelecttime / 1000)); + checkping (); + } + } +}; + +Master::Master() +{ +} + +Master::~Master() +{ +} + +/// Main function +int Master::Run() +{ + sLog.outString( "%s (core-daemon)", _FULLVERSION ); + sLog.outString( "<Ctrl-C> to stop.\n" ); + + sLog.outTitle( " ______ __"); + sLog.outTitle( "/\\__ _\\ __ __/\\ \\__"); + sLog.outTitle( "\\/_/\\ \\/ _ __ /\\_\\ ___ /\\_\\ \\ ,_\\ __ __"); + sLog.outTitle( " \\ \\ \\/\\`'__\\/\\ \\ /' _ `\\/\\ \\ \\ \\/ /\\ \\/\\ \\"); + sLog.outTitle( " \\ \\ \\ \\ \\/ \\ \\ \\/\\ \\/\\ \\ \\ \\ \\ \\_\\ \\ \\_\\ \\"); + sLog.outTitle( " \\ \\_\\ \\_\\ \\ \\_\\ \\_\\ \\_\\ \\_\\ \\__\\\\/`____ \\"); + sLog.outTitle( " \\/_/\\/_/ \\/_/\\/_/\\/_/\\/_/\\/__/ `/___/> \\"); + sLog.outTitle( " C O R E /\\___/"); + sLog.outTitle( "http://TrinityCore.org \\/__/\n"); + + /// worldd PID file creation + std::string pidfile = sConfig.GetStringDefault("PidFile", ""); + if(!pidfile.empty()) + { + uint32 pid = CreatePIDFile(pidfile); + if( !pid ) + { + sLog.outError( "Cannot create PID file %s.\n", pidfile.c_str() ); + return 1; + } + + sLog.outString( "Daemon PID: %u\n", pid ); + } + + ///- Start the databases + if (!_StartDB()) + return 1; + + ///- Initialize the World + sWorld.SetInitialWorldSettings(); + + ///- Catch termination signals + _HookSignals(); + + ///- Launch WorldRunnable thread + ZThread::Thread t(new WorldRunnable); + t.setPriority ((ZThread::Priority )2); + + // set server online + LoginDatabase.PExecute("UPDATE realmlist SET color = 0, population = 0 WHERE id = '%d'",realmID); + +#ifdef WIN32 + if (sConfig.GetBoolDefault("Console.Enable", true) && (m_ServiceStatus == -1)/* need disable console in service mode*/) +#else + if (sConfig.GetBoolDefault("Console.Enable", true)) +#endif + { + ///- Launch CliRunnable thread + ZThread::Thread td1(new CliRunnable); + } + + ZThread::Thread td2(new RARunnable); + + ///- Handle affinity for multiple processors and process priority on Windows + #ifdef WIN32 + { + HANDLE hProcess = GetCurrentProcess(); + + uint32 Aff = sConfig.GetIntDefault("UseProcessors", 0); + if(Aff > 0) + { + ULONG_PTR appAff; + ULONG_PTR sysAff; + + if(GetProcessAffinityMask(hProcess,&appAff,&sysAff)) + { + ULONG_PTR curAff = Aff & appAff; // remove non accessible processors + + if(!curAff ) + { + sLog.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for Trinityd. Accessible processors bitmask (hex): %x",Aff,appAff); + } + else + { + if(SetProcessAffinityMask(hProcess,curAff)) + sLog.outString("Using processors (bitmask, hex): %x", curAff); + else + sLog.outError("Can't set used processors (hex): %x",curAff); + } + } + sLog.outString(); + } + + bool Prio = sConfig.GetBoolDefault("ProcessPriority", false); + +// if(Prio && (m_ServiceStatus == -1)/* need set to default process priority class in service mode*/) + if(Prio) + { + if(SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS)) + sLog.outString("TrinityCore process priority class set to HIGH"); + else + sLog.outError("ERROR: Can't set Trinityd process priority class."); + sLog.outString(); + } + } + #endif + + uint32 realCurrTime, realPrevTime; + realCurrTime = realPrevTime = getMSTime(); + + uint32 socketSelecttime = sWorld.getConfig(CONFIG_SOCKET_SELECTTIME); + + // maximum counter for next ping + uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / socketSelecttime)); + uint32 loopCounter = 0; + + ///- Start up freeze catcher thread + uint32 freeze_delay = sConfig.GetIntDefault("MaxCoreStuckTime", 0); + if(freeze_delay) + { + FreezeDetectorRunnable *fdr = new FreezeDetectorRunnable(); + fdr->SetDelayTime(freeze_delay*1000); + ZThread::Thread t(fdr); + t.setPriority(ZThread::High); + } + + ///- Launch the world listener socket + port_t wsport = sWorld.getConfig (CONFIG_PORT_WORLD); + std::string bind_ip = sConfig.GetStringDefault ("BindIP", "0.0.0.0"); + + if (sWorldSocketMgr->StartNetwork (wsport, bind_ip.c_str ()) == -1) + { + sLog.outError ("Failed to start network"); + World::StopNow(ERROR_EXIT_CODE); + // go down and shutdown the server + } + + sWorldSocketMgr->Wait (); + + // set server offline + LoginDatabase.PExecute("UPDATE realmlist SET color = 2 WHERE id = '%d'",realmID); + + ///- Remove signal handling before leaving + _UnhookSignals(); + + // when the main thread closes the singletons get unloaded + // since worldrunnable uses them, it will crash if unloaded after master + t.wait(); + td2.wait (); + + ///- Clean database before leaving + clearOnlineAccounts(); + + ///- Wait for delay threads to end + CharacterDatabase.HaltDelayThread(); + WorldDatabase.HaltDelayThread(); + LoginDatabase.HaltDelayThread(); + + sLog.outString( "Halting process..." ); + + #ifdef WIN32 + if (sConfig.GetBoolDefault("Console.Enable", true)) + { + // this only way to terminate CLI thread exist at Win32 (alt. way exist only in Windows Vista API) + //_exit(1); + // send keyboard input to safely unblock the CLI thread + INPUT_RECORD b[5]; + HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE); + b[0].EventType = KEY_EVENT; + b[0].Event.KeyEvent.bKeyDown = TRUE; + b[0].Event.KeyEvent.uChar.AsciiChar = 'X'; + b[0].Event.KeyEvent.wVirtualKeyCode = 'X'; + b[0].Event.KeyEvent.wRepeatCount = 1; + + b[1].EventType = KEY_EVENT; + b[1].Event.KeyEvent.bKeyDown = FALSE; + b[1].Event.KeyEvent.uChar.AsciiChar = 'X'; + b[1].Event.KeyEvent.wVirtualKeyCode = 'X'; + b[1].Event.KeyEvent.wRepeatCount = 1; + + b[2].EventType = KEY_EVENT; + b[2].Event.KeyEvent.bKeyDown = TRUE; + b[2].Event.KeyEvent.dwControlKeyState = 0; + b[2].Event.KeyEvent.uChar.AsciiChar = '\r'; + b[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; + b[2].Event.KeyEvent.wRepeatCount = 1; + b[2].Event.KeyEvent.wVirtualScanCode = 0x1c; + + b[3].EventType = KEY_EVENT; + b[3].Event.KeyEvent.bKeyDown = FALSE; + b[3].Event.KeyEvent.dwControlKeyState = 0; + b[3].Event.KeyEvent.uChar.AsciiChar = '\r'; + b[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; + b[3].Event.KeyEvent.wVirtualScanCode = 0x1c; + b[3].Event.KeyEvent.wRepeatCount = 1; + DWORD numb; + BOOL ret = WriteConsoleInput(hStdIn, b, 4, &numb); + } + #endif + + // for some unknown reason, unloading scripts here and not in worldrunnable + // fixes a memory leak related to detaching threads from the module + UnloadScriptingModule(); + + // Exit the process with specified return value + return World::GetExitCode(); +} + +/// Initialize connection to the databases +bool Master::_StartDB() +{ + ///- Get world database info from configuration file + std::string dbstring; + if(!sConfig.GetString("WorldDatabaseInfo", &dbstring)) + { + sLog.outError("Database not specified in configuration file"); + return false; + } + sLog.outString("World Database: %s", dbstring.c_str()); + + ///- Initialise the world database + if(!WorldDatabase.Initialize(dbstring.c_str())) + { + sLog.outError("Cannot connect to world database %s",dbstring.c_str()); + return false; + } + + if(!sConfig.GetString("CharacterDatabaseInfo", &dbstring)) + { + sLog.outError("Character Database not specified in configuration file"); + return false; + } + sLog.outString("Character Database: %s", dbstring.c_str()); + + ///- Initialise the Character database + if(!CharacterDatabase.Initialize(dbstring.c_str())) + { + sLog.outError("Cannot connect to Character database %s",dbstring.c_str()); + return false; + } + + ///- Get login database info from configuration file + if(!sConfig.GetString("LoginDatabaseInfo", &dbstring)) + { + sLog.outError("Login database not specified in configuration file"); + return false; + } + + ///- Initialise the login database + sLog.outString("Login Database: %s", dbstring.c_str() ); + if(!LoginDatabase.Initialize(dbstring.c_str())) + { + sLog.outError("Cannot connect to login database %s",dbstring.c_str()); + return false; + } + + ///- Get the realm Id from the configuration file + realmID = sConfig.GetIntDefault("RealmID", 0); + if(!realmID) + { + sLog.outError("Realm ID not defined in configuration file"); + return false; + } + sLog.outString("Realm running as realm ID %d", realmID); + + ///- Clean the database before starting + clearOnlineAccounts(); + + sWorld.LoadDBVersion(); + + sLog.outString("Using %s", sWorld.GetDBVersion()); + return true; +} + +/// Clear 'online' status for all accounts with characters in this realm +void Master::clearOnlineAccounts() +{ + // Cleanup online status for characters hosted at current realm + /// \todo Only accounts with characters logged on *this* realm should have online status reset. Move the online column from 'account' to 'realmcharacters'? + LoginDatabase.PExecute( + "UPDATE account SET online = 0 WHERE online > 0 " + "AND id IN (SELECT acctid FROM realmcharacters WHERE realmid = '%d')",realmID); + + CharacterDatabase.Execute("UPDATE characters SET online = 0 WHERE online<>0"); + + // Battleground instance ids reset at server restart + CharacterDatabase.Execute("UPDATE characters SET bgid = 0 WHERE bgid<>0"); +} + +/// Handle termination signals +void Master::_OnSignal(int s) +{ + switch (s) + { + case SIGINT: + World::StopNow(RESTART_EXIT_CODE); + break; + case SIGTERM: + #ifdef _WIN32 + case SIGBREAK: + #endif + World::StopNow(SHUTDOWN_EXIT_CODE); + break; + } + + signal(s, _OnSignal); +} + +/// Define hook '_OnSignal' for all termination signals +void Master::_HookSignals() +{ + signal(SIGINT, _OnSignal); + signal(SIGTERM, _OnSignal); + #ifdef _WIN32 + signal(SIGBREAK, _OnSignal); + #endif +} + +/// Unhook the signals before leaving +void Master::_UnhookSignals() +{ + signal(SIGINT, 0); + signal(SIGTERM, 0); + #ifdef _WIN32 + signal(SIGBREAK, 0); + #endif +} diff --git a/src/mangosd/Master.h b/src/mangosd/Master.h new file mode 100644 index 00000000000..3b2b38f32f4 --- /dev/null +++ b/src/mangosd/Master.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup Trinityd +/// @{ +/// \file + +#ifndef _MASTER_H +#define _MASTER_H + +#include "Common.h" +#include "Policies/Singleton.h" + +/// Start the server +class Master +{ + public: + Master(); + ~Master(); + int Run(); + static volatile uint32 m_masterLoopCounter; + + private: + bool _StartDB(); + + void _HookSignals(); + void _UnhookSignals(); + static void _OnSignal(int s); + + void clearOnlineAccounts(); +}; + +#define sMaster Trinity::Singleton<Master>::Instance() +#endif +/// @} diff --git a/src/mangosd/RASocket.cpp b/src/mangosd/RASocket.cpp new file mode 100644 index 00000000000..a48928d5a23 --- /dev/null +++ b/src/mangosd/RASocket.cpp @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup Trinityd +*/ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "Log.h" +#include "RASocket.h" +#include "World.h" +#include "Config/ConfigEnv.h" +#include "Util.h" +#include "AccountMgr.h" + +/// \todo Make this thread safe if in the future 2 admins should be able to log at the same time. +SOCKET r; + +#define dropclient {Sendf("I'm busy right now, come back later."); \ + SetCloseAndDelete(); \ + return; \ + } + +uint32 iSession=0; ///< Session number (incremented each time a new connection is made) +unsigned int iUsers=0; ///< Number of active administrators + +typedef int(* pPrintf)(const char*,...); + +void ParseCommand(CliCommandHolder::Print*, char*command); + +/// RASocket constructor +RASocket::RASocket(ISocketHandler &h): TcpSocket(h) +{ + + ///- Increment the session number + iSess =iSession++ ; + + ///- Get the config parameters + bSecure = sConfig.GetBoolDefault( "RA.Secure", true ); + iMinLevel = sConfig.GetIntDefault( "RA.MinLevel", 3 ); + + ///- Initialize buffer and data + iInputLength=0; + buff=new char[RA_BUFF_SIZE]; + stage=NONE; +} + +/// RASocket destructor +RASocket::~RASocket() +{ + ///- Delete buffer and decrease active admins count + delete [] buff; + + sLog.outRALog("Connection was closed.\n"); + + if(stage==OK) + iUsers--; +} + +/// Accept an incoming connection +void RASocket::OnAccept() +{ + std::string ss=GetRemoteAddress(); + sLog.outRALog("Incoming connection from %s.\n",ss.c_str()); + ///- If there is already an active admin, drop the connection + if(iUsers) + dropclient + + ///- Else print Motd + Sendf("%s\r\n",sWorld.GetMotd()); +} + +/// Read data from the network +void RASocket::OnRead() +{ + ///- Read data and check input length + TcpSocket::OnRead(); + + unsigned int sz=ibuf.GetLength(); + if(iInputLength+sz>=RA_BUFF_SIZE) + { + sLog.outRALog("Input buffer overflow, possible DOS attack.\n"); + SetCloseAndDelete(); + return; + } + + ///- If there is already an active admin (other than you), drop the connection + if(stage!=OK && iUsers) + dropclient + + char *inp = new char [sz+1]; + ibuf.Read(inp,sz); + + /// \todo Can somebody explain this 'Linux bugfix'? + if(stage==NONE) + if(sz>4) //linux remote telnet + if(memcmp(inp ,"USER ",5)) + { + delete [] inp;return; + printf("lin bugfix"); + } //linux bugfix + + ///- Discard data after line break or line feed + bool gotenter=false; + unsigned int y=0; + for(;y<sz;y++) + if(inp[y]=='\r'||inp[y]=='\n') + { + gotenter=true; + break; + } + + //No buffer overflow (checked above) + memcpy(&buff[iInputLength],inp,y); + iInputLength+=y; + delete [] inp; + if(gotenter) + { + + buff[iInputLength]=0; + iInputLength=0; + switch(stage) + { + /// <ul> <li> If the input is 'USER <username>' + case NONE: + if(!memcmp(buff,"USER ",5)) //got "USER" cmd + { + szLogin=&buff[5]; + + ///- Get the gmlevel and password from the account table + std::string login = szLogin; + + ///- Convert Account name to Upper Format + AccountMgr::normilizeString(login); + + ///- Escape the Login to allow quotes in names + LoginDatabase.escape_string(login); + + QueryResult* result = LoginDatabase.PQuery("SELECT gmlevel FROM account WHERE username = '%s'",login.c_str()); + + ///- If the user is not found, deny access + if(!result) + { + Sendf("-No such user.\r\n"); + sLog.outRALog("User %s does not exist.\n",szLogin.c_str()); + if(bSecure)SetCloseAndDelete(); + } + else + { + Field *fields = result->Fetch(); + + //szPass=fields[0].GetString(); + + ///- if gmlevel is too low, deny access + if(fields[0].GetUInt32()<iMinLevel) + { + Sendf("-Not enough privileges.\r\n"); + sLog.outRALog("User %s has no privilege.\n",szLogin.c_str()); + if(bSecure)SetCloseAndDelete(); + } else + { + stage=LG; + } + delete result; + } + } + break; + ///<li> If the input is 'PASS <password>' (and the user already gave his username) + case LG: + if(!memcmp(buff,"PASS ",5)) //got "PASS" cmd + { //login+pass ok + ///- If password is correct, increment the number of active administrators + std::string login = szLogin; + std::string pw = &buff[5]; + + AccountMgr::normilizeString(login); + AccountMgr::normilizeString(pw); + LoginDatabase.escape_string(login); + LoginDatabase.escape_string(pw); + + QueryResult *check = LoginDatabase.PQuery( + "SELECT 1 FROM account WHERE username = '%s' AND sha_pass_hash=SHA1(CONCAT(username,':','%s'))", + login.c_str(), pw.c_str()); + + if(check) + { + delete check; + r=GetSocket(); + stage=OK; + ++iUsers; + + Sendf("+Logged in.\r\n"); + sLog.outRALog("User %s has logged in.\n",szLogin.c_str()); + Sendf("TC>"); + } + else + { + ///- Else deny access + Sendf("-Wrong pass.\r\n"); + sLog.outRALog("User %s has failed to log in.\n",szLogin.c_str()); + if(bSecure)SetCloseAndDelete(); + } + } + break; + ///<li> If user is logged, parse and execute the command + case OK: + if(strlen(buff)) + { + sLog.outRALog("Got '%s' cmd.\n",buff); + sWorld.QueueCliCommand(&RASocket::zprint , buff); + } + else + Sendf("TC>"); + break; + ///</ul> + }; + + } +} + +/// Output function +void RASocket::zprint( const char * szText ) +{ + if( !szText ) + return; + + #ifdef RA_CRYPT + + char *megabuffer=strdup(szText); + unsigned int sz=strlen(megabuffer); + Encrypt(megabuffer,sz); + send(r,megabuffer,sz,0); + delete [] megabuffer; + + #else + + unsigned int sz=strlen(szText); + send(r,szText,sz,0); + + #endif +} diff --git a/src/trinitycore/RASocket.h b/src/mangosd/RASocket.h index a164c9d3aa2..8900e689b2c 100644 --- a/src/trinitycore/RASocket.h +++ b/src/mangosd/RASocket.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/trinitycore/TrinityCore.ico b/src/mangosd/TrinityCore.ico Binary files differindex 6f0a5721957..6f0a5721957 100644 --- a/src/trinitycore/TrinityCore.ico +++ b/src/mangosd/TrinityCore.ico diff --git a/src/mangosd/WorldRunnable.cpp b/src/mangosd/WorldRunnable.cpp new file mode 100644 index 00000000000..0229f7f0f5c --- /dev/null +++ b/src/mangosd/WorldRunnable.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup Trinityd +*/ + +#include "WorldSocketMgr.h" +#include "Common.h" +#include "World.h" +#include "WorldRunnable.h" +#include "Timer.h" +#include "ObjectAccessor.h" +#include "MapManager.h" +#include "BattleGroundMgr.h" + +#include "Database/DatabaseEnv.h" + +#ifdef WIN32 +#define WORLD_SLEEP_CONST 50 +#else +#define WORLD_SLEEP_CONST 100 //Is this still needed?? [On linux some time ago not working 50ms] +#endif + +/// Heartbeat for the World +void WorldRunnable::run() +{ + ///- Init new SQL thread for the world database + WorldDatabase.ThreadStart(); // let thread do safe mySQL requests (one connection call enough) + sWorld.InitResultQueue(); + + uint32 realCurrTime = 0; + uint32 realPrevTime = getMSTime(); + + uint32 prevSleepTime = 0; // used for balanced full tick time length near WORLD_SLEEP_CONST + + ///- While we have not World::m_stopEvent, update the world + while (!World::IsStopped()) + { + ++World::m_worldLoopCounter; + realCurrTime = getMSTime(); + + uint32 diff = getMSTimeDiff(realPrevTime,realCurrTime); + + sWorld.Update( diff ); + realPrevTime = realCurrTime; + + // diff (D0) include time of previous sleep (d0) + tick time (t0) + // we want that next d1 + t1 == WORLD_SLEEP_CONST + // we can't know next t1 and then can use (t0 + d1) == WORLD_SLEEP_CONST requirement + // d1 = WORLD_SLEEP_CONST - t0 = WORLD_SLEEP_CONST - (D0 - d0) = WORLD_SLEEP_CONST + d0 - D0 + if (diff <= WORLD_SLEEP_CONST+prevSleepTime) + { + prevSleepTime = WORLD_SLEEP_CONST+prevSleepTime-diff; + ZThread::Thread::sleep(prevSleepTime); + } + else + prevSleepTime = 0; + } + + sWorld.KickAll(); // save and kick all players + sWorld.UpdateSessions( 1 ); // real players unload required UpdateSessions call + + // unload battleground templates before different singletons destroyed + sBattleGroundMgr.DeleteAlllBattleGrounds(); + + sWorldSocketMgr->StopNetwork(); + + MapManager::Instance().UnloadAll(); // unload all grids (including locked in memory) + + ///- End the database thread + WorldDatabase.ThreadEnd(); // free mySQL thread resources +} diff --git a/src/mangosd/WorldRunnable.h b/src/mangosd/WorldRunnable.h new file mode 100644 index 00000000000..b967d0dac0b --- /dev/null +++ b/src/mangosd/WorldRunnable.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup Trinityd +/// @{ +/// \file + +#ifndef __WORLDRUNNABLE_H +#define __WORLDRUNNABLE_H + +/// Heartbeat thread for the World +class WorldRunnable : public ZThread::Runnable +{ + public: + void run(); +}; +#endif +/// @} diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in new file mode 100644 index 00000000000..516a6bc2a62 --- /dev/null +++ b/src/mangosd/mangosd.conf.dist.in @@ -0,0 +1,1448 @@ +########################################## +# Trinity Core worldd configuration file # +########################################## +ConfVersion=2008080101 + +################################################################################################################### +# CONNECTIONS AND DIRECTORIES +# +# RealmID +# RealmID must match the realmlist inside the realmd database +# +# DataDir +# Data directory setting. +# Important: DataDir needs to be quoted, as it is a string which may contain space characters. +# Example: "@prefix@/share/trinitycore" +# +# LogsDir +# Logs directory setting. +# Important: Logs dir must exists, or all logs need to be disabled +# Default: "" - no log directory prefix, if used log names isn't absolute path +# then logs will be stored in current directory for run program. +# +# +# LoginDatabaseInfo +# WorldDatabaseInfo +# CharacterDatabaseInfo +# Database connection settings for the world server. +# Default: hostname;port;username;password;database +# .;somenumber;username;password;database - use named pipes at Windows +# Named pipes: mySQL required adding "enable-named-pipe" to [mysqld] section my.ini +# .;/path/to/unix_socket;username;password;database - use Unix sockets at Unix/Linux +# Unix sockets: experimental, not tested +# +# MaxPingTime +# Settings for maximum database-ping interval (minutes between pings) +# +# WorldServerPort +# Default WorldServerPort +# +# BindIP +# Bind World Server to IP/hostname +# +################################################################################################################### + +RealmID = 1 +DataDir = "." +LogsDir = "" +LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;realmd" +WorldDatabaseInfo = "127.0.0.1;3306;trinity;trinity;world" +CharacterDatabaseInfo = "127.0.0.1;3306;trinity;trinity;characters" +MaxPingTime = 30 +WorldServerPort = 8085 +BindIP = "0.0.0.0" + +################################################################################################################### +# SCRIPTING SETTINGS +# +# Locale +# Setting for current (DBC) locale to use +# +# EventAI Error reporting +# 0 - Only startup (Default) +# 1 - Startup errors and Runtime event errors +# 2 - Startup errors, Runtime event errors, and Creation errors +################################################################################################################### + +Locale = 0 +EAIErrorLevel = 2 + +################################################################################################################### +# PERFORMANCE SETINGS +# +# UseProcessors +# Used processors mask for multi-processors system (Used only at Windows) +# Default: 0 (selected by OS) +# number (bitmask value of selected processors) +# +# ProcessPriority +# Process priority setting (Used only at Windows) +# Default: 1 (HIGH) +# 0 (Normal) +# +# Compression +# Compression level for update packages sent to client (1..9) +# Default: 1 (speed) +# 9 (best compression) +# +# PlayerLimit +# Maximum number of players in the world. Excluding Mods, GM's and Admins +# Default: 100 +# 0 (for infinite players) +# -1 (for Mods, GM's and Admins only) +# -2 (for GM's and Admins only) +# -3 (for Admins only) +# +# SaveRespawnTimeImmediately +# Save respawn time for creatures at death and for gameobjects at use/open +# Default: 1 (save creature/gameobject respawn time without waiting grid unload) +# 0 (save creature/gameobject respawn time at grid unload) +# +# MaxOverspeedPings +# Maximum overspeed ping count before player kick (minimum is 2, 0 used for disable check) +# Default: 2 +# +# GridUnload +# Unload grids (if you have lot memory you can disable it to speed up player move to new grids second time) +# Default: 1 (unload grids) +# 0 (do not unload grids) +# +# SocketSelectTime +# Socket select time (in milliseconds) +# Default: 10000 +# +# GridCleanUpDelay +# Grid clean up delay (in milliseconds) +# Default: 300000 (5 min) +# +# MapUpdateInterval +# Map update interval (in milliseconds) +# Default: 100 +# +# ChangeWeatherInterval +# Weather update interval (in milliseconds) +# Default: 600000 (10 min) +# +# PlayerSaveInterval +# Player save interval (in milliseconds) +# Default: 900000 (15 min) +# +# vmap.enableLOS +# vmap.enableHeight +# Enable/Disable VMmap support for line of sight and height calculation +# Default: 1 (true) +# 0 (false) +# +# vmap.ignoreMapIds +# Map id that will be ignored by VMaps +# List of ids with delimiter ',' +# If more then one id is defined and spaces are included, the string has to be enclosed by " +# Example: "369,0,1,530" +# +# vmap.ignoreSpellIds +# These spells are ignored for LoS calculation +# List of ids with delimiter ',' +# +# DetectPosCollision +# Check final move position, summon position, etc for visible collision with other objects or +# wall (wall only if vmaps are enabled) +# Default: 1 (enable, required more CPU power usage) +# 0 (disable, less nice position selection but will less CPU power usage) +# +# TargetPosRecalculateRange +# Max distance from movement target point (+moving unit size) and targeted object (+size) +# after that new target movmeent point calculated. Max: melee attack range (5), min: contact range (0.5) +# More distance let have better performence, less distance let have more sensitive reaction at target move. +# Default: 1.5 +# +# UpdateUptimeInterval +# Update realm uptime period in minutes (for save data in 'uptime' table). Must be > 0 +# Default: 10 (minutes) +# +# MaxCoreStuckTime +# Periodically check if the process got freezed, if this is the case force crash after the specified +# amount of seconds. Must be > 0. Recommended > 10 secs if you use this. +# Default: 0 (Disabled) +# +# AddonChannel +# Permit/disable the use of the addon channel through the server +# (some client side addons can stop work correctly with disabled addon channel) +# Default: 1 (permit addon channel) +# 0 (do not permit addon channel) +# +################################################################################################################### + +UseProcessors = 0 +ProcessPriority = 1 +Compression = 1 +PlayerLimit = 100 +SaveRespawnTimeImmediately = 1 +MaxOverspeedPings = 2 +GridUnload = 1 +SocketSelectTime = 10000 +GridCleanUpDelay = 300000 +MapUpdateInterval = 100 +ChangeWeatherInterval = 600000 +PlayerSaveInterval = 900000 +vmap.enableLOS = 0 +vmap.enableHeight = 0 +vmap.ignoreMapIds = "369" +vmap.ignoreSpellIds = "7720" +DetectPosCollision = 1 +TargetPosRecalculateRange = 1.5 +UpdateUptimeInterval = 10 +MaxCoreStuckTime = 0 +AddonChannel = 1 + +################################################################################################################### +# SERVER LOGGING +# +# LogSQL +# Enable logging of GM commands - all SQL code will be written to a log file +# All commands are written to a file: YYYY-MM-DD_logSQL.sql +# If a new day starts (00:00:00) then a new file is created - the old file will not be deleted. +# Default: 1 - Write SQL code to logfile +# 0 - Do not log +# +# PidFile +# World daemon PID file +# Default: "" - do not create PID file +# "./worldd.pid" - create PID file (recommended name) +# +# LogLevel +# Server console level of logging +# 0 = Minimum; 1 = Basic&Error; 2 = Detail; 3 = Full/Debug +# Default: 3 +# +# LogTime +# Include time in server console output [hh:mm:ss] +# Default: 0 (no time) +# 1 (print time) +# +# LogFile +# Logfile name +# Default: "Server.log" +# "" - Empty name disable creating log file +# +# LogTimestamp +# Logfile with timestamp of server start in name +# Default: 0 - no timestamp in name +# 1 - add timestamp in name in form Logname_YYYY-MM-DD_HH-MM-SS.Ext for Logname.Ext +# +# LogFileLevel +# Server file level of logging +# 0 = Minimum; 1 = Error; 2 = Detail; 3 = Full/Debug +# Default: 0 +# +# LogFilter_TransportMoves +# LogFilter_CreatureMoves +# LogFilter_VisibilityChanges +# Log filters +# Default: 1 - not include with any log level +# 0 - include in log if log level permit +# +# WorldLogFile +# Packet logging file for the worldserver +# Default: "world.log" +# +# DBErrorLogFile +# Log file of DB errors detected at server run +# Default: "DBErrors.log" +# +# CharLogFile +# Character operations logfile name +# Default: "Char.log" +# "" - Empty name disable creating log file +# +# CharLogTimestamp +# Logfile with timestamp of server start in name +# Default: 0 - no timestamp in name +# 1 - add timestamp in name in form Logname_YYYY-MM-DD_HH-MM-SS.Ext for Logname.Ext +# +# CharLogDump +# Write character dump before deleting in Char.log +# For restoration, cut character data from log starting from +# line == START DUMP == to line == END DUMP == (without its) in file and load it using loadpdump command +# Default: 0 - don't include dumping chars to log +# 1 - include dumping chars to log +# +# GmLogFile +# Log file of gm commands +# Default: "gm_commands.log" +# "" - Empty name for disable +# +# GmLogTimestamp +# GM Logfile with timestamp of server start in name +# Default: 0 - no timestamp in name +# 1 - add timestamp in name in form Logname_YYYY-MM-DD_HH-MM-SS.Ext for Logname.Ext +# +# GmLogPerAccount +# GM Logfiles with GM account id (Note: logs not created if GmLogFile not set) +# Default: 0 - add gm log data to single log file +# 1 - add gm log data to account specific log files with name +# in form Logname_#ID_YYYY-MM-DD_HH-MM-SS.Ext +# or form Logname_#ID.Ext +# +# RaLogFile +# Log file of RA commands +# Default: "Ra.log" +# "" - Empty name for disable +# +# LogColors +# Color for messages (format "normal_color details_color debug_color error_color") +# Colors: 0 - BLACK, 1 - RED, 2 - GREEN, 3 - BROWN, 4 - BLUE, 5 - MAGENTA, 6 - CYAN, 7 - GREY, +# 8 - YELLOW, 9 - LRED, 10 - LGREEN, 11 - LBLUE, 12 - LMAGENTA, 13 - LCYAN, 14 - WHITE +# Default: "" - none colors +# Example: "13 7 11 9" +# +################################################################################################################### + +LogSQL = 1 +PidFile = "" +LogLevel = 1 +LogTime = 0 +LogFile = "Server.log" +LogTimestamp = 0 +LogFileLevel = 0 +LogFilter_TransportMoves = 1 +LogFilter_CreatureMoves = 1 +LogFilter_VisibilityChanges = 1 +WorldLogFile = "" +DBErrorLogFile = "db_errors.log" +CharLogFile = "characters.log" +CharLogTimestamp = 0 +CharLogDump = 0 +GmLogFile = "gm_commands.log" +GmLogTimestamp = 0 +GmLogPerAccount = 0 +RaLogFile = "ra_commands.log" +LogColors = "" + +################################################################################################################### +# SERVER SETTINGS +# +# GameType +# Server realm style +# 0 = NORMAL;1 = PVP; 4 = NORMAL; 6 = RP; 8 = RPPVP +# also custom type: 16 FFA_PVP (free for all pvp mode like arena PvP in all zones except rest +# activated places and sanctuaries) +# +# RealmZone +# Server realm zone (set allowed alphabet in character names/etc). See also Strict*Names options. +# +# 1 Development - any language (Default) +# 2 United States - extended-Latin +# 3 Oceanic - extended-Latin +# 4 Latin America - extended-Latin +# 5 Tournament - basic-Latin at create, any at login +# 6 Korea - East-Asian +# 7 Tournament - basic-Latin at create, any at login +# 8 English - extended-Latin +# 9 German - extended-Latin +# 10 French - extended-Latin +# 11 Spanish - extended-Latin +# 12 Russian - Cyrillic +# 13 Tournament - basic-Latin at create, any at login +# 14 Taiwan - East-Asian +# 15 Tournament - basic-Latin at create, any at login +# 16 China - East-Asian +# 17 CN1 - basic-Latin at create, any at login +# 18 CN2 - basic-Latin at create, any at login +# 19 CN3 - basic-Latin at create, any at login +# 20 CN4 - basic-Latin at create, any at login +# 21 CN5 - basic-Latin at create, any at login +# 22 CN6 - basic-Latin at create, any at login +# 23 CN7 - basic-Latin at create, any at login +# 24 CN8 - basic-Latin at create, any at login +# 25 Tournament - basic-Latin at create, any at login +# 26 Test Server - any language +# 27 Tournament - basic-Latin at create, any at login +# 28 QA Server - any language +# 29 CN9 - basic-Latin at create, any at login +# +# Expansion +# Allow server use content from expansion +# Default: 2 - check expansion 2 maps existence, and if client support expansion 2 and account have +# expansion 2 setting then allow visit expansion 2 maps, allow create new class character) +# 1 - check expansion 1 maps existence, and if client support expansion 1 and account have +# expansion 1 setting then allow visit expansion 1 maps, allow create new races character) +# 0 - not check expansion maps existence, not allow wisit its, not allow create new race or new class +# characters, ignore account expansion setting) +# +# DBC.Locale +# DBC Language Settings +# 0 = English; 1 = Korean; 2 = French; 3 = German; 4 = Chinese; 5 = Taiwanese; 6 = Spanish; 7 = Spanish Mexico +# 8 = Russian; 255 = Auto Detect (Default) +# +# DeclinedNames +# Allow russian clients to set and use declined names +# Default: 0 - do not use declined names, except when the Russian RealmZone is set +# 1 - use declined names +# +# StrictPlayerNames +# Limit player name to language specific symbols set, not allow create characters, and set rename request and disconnect at not allowed symbols name +# Default: 0 disable (but limited server timezone dependent client check) +# 1 basic latin characters (strict) +# 2 realm zone specific (strict). See RealmZone setting. +# Note: In any case if you want correctly see character name at client this client must have apporopriate fonts +# (included in client by default, with active official localization or custom localization fonts in clientdir/Fonts). +# 3 basic latin characters + server timezone specific +# +# StrictCharterNames +# Limit guild/arena team charter names to language specific symbols set, not allow create charters with allowed symbols in name +# Default: 0 disable +# 1 basic latin characters (strict) +# 2 realm zone specific (strict). See RealmZone setting. +# Note: In any case if you want correctly see character name at client this client must have apporopriate fonts +# (included in client by default, with active official localization or custom localization fonts in clientdir/Fonts). +# 3 basic latin characters + server timezone specific +# +# StrictPetNames +# Limit pet names to language specific symbols set +# Default: 0 disable +# 1 basic latin characters (strict) +# 2 realm zone specific (strict). See RealmZone setting. +# Note: In any case if you want correctly see character name at client this client must have apporopriate fonts +# (included in client by default, with active official localization or custom localization fonts in clientdir/Fonts). +# 3 basic latin characters + server timezone specific +# +# CharactersCreatingDisabled +# Disable characters creating for specific team or any (non-player accounts not affected) +# Default: 0 - enabled +# 1 - disabled only for Alliance +# 2 - disabled only for Horde +# 3 - disabled for both teams +# +# MaxWhoListReturns +# Set the maximum number of players returned in the /who list and interface. +# Default: 49 (stable) +# +# CharactersPerAccount +# Limit numbers of characters per account (at all realms). +# Note: this setting limit character creating at _current_ realm base at characters amount at all realms +# Default: 50 +# The number must be >= CharactersPerRealm +# +# CharactersPerRealm +# Limit numbers of characters for account at realm +# Default: 10 (client limitation) +# The number must be between 1 and 10 +# +# HeroicCharactersPerRealm +# Limit numbers of heroic class characters for account at realm +# Default: 1 +# The number must be between 0 (not allowed) and 10 +# +# MinLevelForHeroicCharacterCreating +# Limit creating heroic characters only for account with another character of specific level (ignored for GM accounts) +# 0 - not require any existed chaarcter +# 1 - require at least any character existed +# Default: 55 - default requirement +# +# +# SkipCinematics +# Disable in-game script movie at first character's login(allows to prevent buggy intro in case of custom start location coordinates) +# Default: 0 - show intro for each new characrer +# 1 - show intro only for first character of selected race +# 2 - disable intro show in all cases +# +# MaxPlayerLevel +# Max level that can be reached by player for experience (in range from 1 to 100). +# Change not recommended +# Default: 80 +# +# StartPlayerLevel +# Staring level that have character at creating (in range 1 to MaxPlayerLevel) +# Default: 1 +# +# StartHeroicPlayerLevel +# Staring level that have character of heroic class at creating (in range 1 to MaxPlayerLevel) +# Default: 55 +# +# StartPlayerMoney +# Amount of money that new players will start with. +# If you want to start with silver, use for example 100 (100 copper = 1 silver) +# Default: 0 +# +# MaxHonorPoints +# Max honor points that player can have. +# Default: 75000 +# +# StartHonorPoints +# Amount of honor that new players will start with +# Default: 0 +# +# MaxArenaPoints +# Max arena points that player can have. +# Default: 5000 +# +# StartArenaPoints +# Amount of arena points that new players will start with +# Default: 0 +# +# InstantLogout +# Enable or disable instant logout for security level (0..4) or high (NOT in combat/while dueling/while falling) +# Default: 1 (Mods/GMs/Admins) +# +# DisableWaterBreath +# Disable/enable waterbreathing for security level (0..4) or high +# Default: 4 (None) +# +# AllFlightPaths +# Players will start with all flight paths (Note: ALL flight paths, not only player's team) +# Default: 0 (true) +# 1 (false) +# +# AlwaysMaxSkillForLevel +# Players will automatically gain max level dependent (weapon/defense) skill when logging in, leveling up etc. +# Default: 0 (false) +# 1 (true) +# +# ActivateWeather +# Activate weather system +# Default: 1 (true) +# 0 (false) +# +# Battleground.CastDeserter +# Cast or not Deserter spell at player who leave battleground in progress +# Default: 1 (true) +# 0 (false) +# +# Battleground.QueueAnnouncer.Enable +# Enable queue announcer posting to chat +# Default: 0 (false) +# 1 (true) +# +# Battleground.QueueAnnouncer.PlayerOnly +# Enable queue announcer posting to chat +# Default: 0 (false) +# 1 (true) +# +# Arena.QueueAnnouncer.Enable: Enable queue announcer posting to chat +# Default: 0 (false) +# 1 (true) +# +# CastUnstuck +# Allow cast or not Unstuck spell at .start or client Help option use +# Default: 1 (true) +# 0 (false) +# +# Instance.IgnoreLevel +# Ignore level requirement to enter instance +# Default: 0 (false) +# 1 (true) +# +# Instance.IgnoreRaid +# Ignore raid requirement to enter instance +# Default: 0 (false) +# 1 (true) +# +# Instance.ResetTimeHour +# The hour of the day (0-23) when the global instance resets occur. +# Default: 4 +# +# Instance.UnloadDelay +# Unload the instance map from memory after some time if no players are inside. +# Default: 1800000 (miliseconds, i.e 30 minutes) +# 0 (instance maps are kept in memory until they are reset) +# +# Quests.LowLevelHideDiff +# Quest level difference to hide for player low level quests: +# if player_level > quest_level + LowLevelQuestsHideDiff then quest "!" mark not show for quest giver +# Default: 4 +# -1 (show all available quests marks) +# +# Quests.HighLevelHideDiff +# Quest level difference to hide for player high level quests: +# if player_level < quest_min_level - HighLevelQuestsHideDiff then quest "!" mark not show for quest giver +# Default: 7 +# -1 (show all available quests marks) +# +# MaxPrimaryTradeSkill +# Max count that player can learn the primary trade skill. +# Default: 2 +# Max : 10 +# +# MinPetitionSigns +# Min signatures count to creating guild (0..9). +# Default: 9 +# +# MaxGroupXPDistance +# Max distance to creature for group memeber to get XP at creature death. +# Default: 74 +# +# MailDeliveryDelay +# Mail delivery delay time for item sending +# Default: 3600 sec (1 hour) +# +# SkillChance.Prospecting +# For prospecting skillup impossible by default, but can be allowed as custom setting +# Default: 0 - no skilups +# 1 - skilups possible +# +# SkillChance.Milling +# For milling skillup impossible by default, but can be allowed as custom setting +# Default: 0 - no skilups +# 1 - skilups possible +# +# Event.Announce +# Default: 0 (false) +# 1 (true) +# +# BeepAtStart +# Beep at core start finished (mostly work only at Unix/Linux systems) +# Default: 1 (true) +# 0 (false) +# +# Motd +# Message of the Day. Displayed at worldlogin for every user ('@' for a newline). +# +# Server.LoginInfo +# Enable/disable sending server info (core version) on login. +# Default: 0 - disable +# 1 - enable +# +################################################################################################################### + +GameType = 1 +RealmZone = 1 +Expansion = 2 +DBC.Locale = 255 +DeclinedNames = 0 +StrictPlayerNames = 0 +StrictCharterNames = 0 +StrictPetNames = 0 +MaxWhoListReturns = 49 +CharactersCreatingDisabled = 0 +CharactersPerAccount = 50 +CharactersPerRealm = 10 +HeroicCharactersPerRealm = 1 +MinLevelForHeroicCharacterCreating = 55 +SkipCinematics = 0 +MaxPlayerLevel = 80 +StartPlayerLevel = 1 +StartHeroicPlayerLevel = 55 +StartPlayerMoney = 0 +MaxHonorPoints = 75000 +StartHonorPoints = 0 +MaxArenaPoints = 5000 +StartArenaPoints = 0 +InstantLogout = 1 +DisableWaterBreath = 4 +AllFlightPaths = 0 +AlwaysMaxSkillForLevel = 0 +ActivateWeather = 1 +Battleground.CastDeserter = 1 +Battleground.QueueAnnouncer.Enable = 0 +Battleground.QueueAnnouncer.PlayerOnly = 0 +Arena.QueueAnnouncer.Enable = 0 +CastUnstuck = 1 +Instance.IgnoreLevel = 0 +Instance.IgnoreRaid = 0 +Instance.ResetTimeHour = 4 +Instance.UnloadDelay = 1800000 +Quests.LowLevelHideDiff = 4 +Quests.HighLevelHideDiff = 7 +MaxPrimaryTradeSkill = 2 +MinPetitionSigns = 9 +MaxGroupXPDistance = 74 +MailDeliveryDelay = 3600 +SkillChance.Prospecting = 0 +SkillChance.Milling = 0 +Event.Announce = 0 +BeepAtStart = 1 +Motd = "Welcome to a Trinity Core server." +Server.LoginInfo = 0 + +################################################################################################################### +# PLAYER INTERACTION +# +# AllowTwoSide.Accounts +# Allow or not accounts to create characters in the 2 teams in any game type. +# Default: 0 (Not allowed) +# 1 (Allowed) +# +# AllowTwoSide.Interaction.Chat +# AllowTwoSide.Interaction.Channel +# AllowTwoSide.Interaction.Group +# AllowTwoSide.Interaction.Guild +# AllowTwoSide.Interaction.Auction +# AllowTwoSide.Interaction.Mail +# Allow or not common :chat(say,yell);channel(chat)group(join)guild(join);merge all auction houses for players from +# different teams, send mail to different team. +# Default: 0 (Not allowed) +# 1 (Allowed) +# +# AllowTwoSide.WhoList +# Allow or not show player from both team in who list. +# Default: 0 (Not allowed) +# 1 (Allowed) +# +# AllowTwoSide.AddFriend +# Allow or not adding friends from other team in friend list. +# Default: 0 (Not allowed) +# 1 (Allowed) +# +# AllowTwoSide.Trade +# Allow or not trading with other team in party. +# Default: 0 (Not allowed) +# 1 (Allowed) +# +# TalentsInspecting +# Allow other players see character talents in inspect dialog (Characters in Gamemaster mode can +# inspect talents always) +# Default: 1 (allow) +# 0 (not allow) +# +################################################################################################################### + +AllowTwoSide.Accounts = 0 +AllowTwoSide.Interaction.Chat = 0 +AllowTwoSide.Interaction.Channel = 0 +AllowTwoSide.Interaction.Group = 0 +AllowTwoSide.Interaction.Guild = 0 +AllowTwoSide.Interaction.Auction = 0 +AllowTwoSide.Interaction.Mail = 0 +AllowTwoSide.WhoList = 0 +AllowTwoSide.AddFriend = 0 +AllowTwoSide.Trade = 0 +TalentsInspecting = 1 + +################################################################################################################### +# CREATURE SETTINGS +# +# ThreatRadius +# Radius for creature to evade after being pulled away from combat start point +# If ThreatRadius is less than creature aggro radius then aggro radius will be used +# Default: 60 yards +# +# Rate.Creature.Aggro +# Aggro radius percent or off. +# Default: 1 - 100% +# 1.5 - 150% +# 0 - off (0%) +# +# CreatureFamilyAssistanceRadius +# Creature family assistance radius +# Default: 10 +# 0 - off +# +# CreatureFamilyAssistanceDelay +# Reaction time for creature assistance call +# Default: 1500 (1.5s) +# +# WorldBossLevelDiff +# Difference for boss dynamic level with target +# Default: 3 +# +# Corpse.Decay.NORMAL +# Corpse.Decay.RARE +# Corpse.Decay.ELITE +# Corpse.Decay.RAREELITE +# Corpse.Decay.WORLDBOSS +# Seconds until creature corpse will decay without being looted or skinned. +# Default: 60, 300, 300, 300, 3600 +# +# Rate.Corpse.Decay.Looted +# Controls how long the creature corpse stays after it had been looted, as a multiplier of its Corpse.Decay.* config. +# Default: 0.5 +# +# Rate.Creature.Normal.Damage +# Rate.Creature.Elite.Elite.Damage +# Rate.Creature.Elite.RAREELITE.Damage +# Rate.Creature.Elite.WORLDBOSS.Damage +# Rate.Creature.Elite.RARE.Damage +# Creature Damage Rates. +# Examples: 2 - creatures will damage 2x, 1.7 - 1.7x. +# +# Rate.Creature.Normal.SpellDamage +# Rate.Creature.Elite.Elite.SpellDamage +# Rate.Creature.Elite.RAREELITE.SpellDamage +# Rate.Creature.Elite.WORLDBOSS.SpellDamag +# Rate.Creature.Elite.RARE.SpellDamage +# Creature Spell Damage Rates. +# Examples: 2 - creatures will damage with spells 2x, 1.7 - 1.7x. +# +# Rate.Creature.Normal.HP +# Rate.Creature.Elite.Elite.HP +# Rate.Creature.Elite.RAREELITE.HP +# Rate.Creature.Elite.WORLDBOSS.HP +# Rate.Creature.Elite.RARE.HP +# Creature Health Ammount Modifier. +# Examples: 2 - creatures have 2x health, 1.7 - 1.7x. +# +# ListenRange.Say +# Distance from player to listen text that creature (or other world object) say +# Default: 25 +# +# ListenRange.TextEmote +# Distance from player to listen textemote that creature (or other world object) say +# Default: 25 +# +# ListenRange.Yell +# Distance from player to listen text that creature (or other world object) yell +# Default: 300 +# +################################################################################################################### + +ThreatRadius = 60 +Rate.Creature.Aggro = 1 +CreatureFamilyAssistanceRadius = 10 +CreatureFamilyAssistanceDelay = 1500 +WorldBossLevelDiff = 3 +Corpse.Decay.NORMAL = 60 +Corpse.Decay.RARE = 300 +Corpse.Decay.ELITE = 300 +Corpse.Decay.RAREELITE = 300 +Corpse.Decay.WORLDBOSS = 3600 +Rate.Corpse.Decay.Looted = 0.5 +Rate.Creature.Normal.Damage = 1 +Rate.Creature.Elite.Elite.Damage = 1 +Rate.Creature.Elite.RAREELITE.Damage = 1 +Rate.Creature.Elite.WORLDBOSS.Damage = 1 +Rate.Creature.Elite.RARE.Damage = 1 +Rate.Creature.Normal.SpellDamage = 1 +Rate.Creature.Elite.Elite.SpellDamage = 1 +Rate.Creature.Elite.RAREELITE.SpellDamage = 1 +Rate.Creature.Elite.WORLDBOSS.SpellDamage = 1 +Rate.Creature.Elite.RARE.SpellDamage = 1 +Rate.Creature.Normal.HP = 1 +Rate.Creature.Elite.Elite.HP = 1 +Rate.Creature.Elite.RAREELITE.HP = 1 +Rate.Creature.Elite.WORLDBOSS.HP = 1 +Rate.Creature.Elite.RARE.HP = 1 +ListenRange.Say = 40 +ListenRange.TextEmote = 40 +ListenRange.Yell = 300 + +################################################################################################################### +# CHAT SETTINGS +# +# ChatFakeMessagePreventing +# Chat protection from creating fake messages using a lot spaces (other invisible symbols), +# not applied to addon language messages, but can prevent working old addons +# that use normal languages for sending data to another clients. +# Default: 0 (disible fake messages preventing) +# 1 (enabled fake messages preventing) +# +# ChatFlood.MessageCount +# Chat anti-flood protection, haste message count to activate protection +# Default: 10 +# 0 (disible anti-flood protection) +# +# ChatFlood.MessageDelay +# Chat anti-flood protection, minimum message delay to count message +# Default: 1 (in secs) +# +# ChatFlood.MuteTime +# Chat anti-flood protection, mute time at activation flood protection (not saved) +# Default: 10 (in secs) +# +# Channel.RestrictedLfg +# Restrict use LookupForGroup channel only registered in LFG tool players +# Default: 1 (allow join to channel only if active in LFG) +# 0 (allow join to channel in any time) +# +# Channel.SilentlyGMJoin +# Silently join GM characters (security level > 1) to channels +# Default: 0 (join announcement in normal way) +# 1 (GM join without announcement) +# +################################################################################################################### + +ChatFakeMessagePreventing = 0 +ChatFlood.MessageCount = 10 +ChatFlood.MessageDelay = 1 +ChatFlood.MuteTime = 10 +Channel.RestrictedLfg = 1 +Channel.SilentlyGMJoin = 0 + +################################################################################################################### +# GAME MASTER SETTINGS +# +# GM.LoginState +# GM mode at login +# Default: 2 (last save state) +# 0 (disable) +# 1 (enable) +# +# GM.Visible +# GM visibility at login +# Default: 2 (last save state) +# 0 (invisible) +# 1 (visible) +# +# GM.AcceptTickets +# Is GM accepting tickets from player by default or not. +# Default: 2 (last save state) +# 0 (disable) +# 1 (enable) +# +# GM.Chat +# GM chat mode at login +# Default: 2 (last save state) +# 0 (disable) +# 1 (enable) +# +# GM.WhisperingTo +# Is GM accepting whispers from player by default or not. +# Default: 2 (last save state) +# 0 (disable) +# 1 (enable) +# +# GM.InGMList +# Is GM showed in GM list (if visible) in non-GM state (.gmoff) +# Default: 0 (false) +# 1 (true) +# +# GM.InWhoList +# Is GM showed in who list (if visible). +# Default: 0 (false) +# 1 (true) +# +# GM.LogTrade +# Include GM trade and trade slot enchanting operations in GM log if it enable +# Default: 1 (include) +# 0 (not include) +# +# GM.StartLevel +# GM starting level (1-100) +# Default: 1 +# +# GM.LowerSecurity +# Disallow a lower security member to interact with a higher one using commands +# Default: 0 (disable) +# 1 (enable) +# +# GM.AllowAchievementGain +# If enabled it allows gaining achievements for GM characters +# Default: 0 (disable) +# 1 (enable) (default) +# +################################################################################################################### + +GM.LoginState = 2 +GM.Visible = 2 +GM.AcceptTickets = 2 +GM.Chat = 2 +GM.WhisperingTo = 2 +GM.InGMList = 0 +GM.InWhoList = 0 +GM.LogTrade = 1 +GM.StartLevel = 80 +GM.LowerSecurity = 0 +GM.AllowAchievementGain = 1 + +################################################################################################################### +# VISIBILITY AND RADIUSES +# +# Visibility.GroupMode +# Group visibility modes +# Default: 0 (standard setting: only members from same group can 100% auto detect invisible player) +# 1 (raid members 100% auto detect invisible player from same raid) +# 2 (players from same team can 100% auto detect invisible player) +# +# Visibility.Distance.Creature +# Visibility.Distance.Player +# Visibility distance for different in game object +# Max limited by active player zone: ~ 166 +# Min limit dependent from objects +# Default: 66 (cell size) +# Min limit is max aggro radius (45) * Rate.Creature.Aggro +# +# Visibility.Distance.Object +# Visible distance for gameobject, dynobject, bodies, corpses, bones +# Min limit is iteraction distance (5) +# +# Visibility.Distance.InFlight +# Visible distance for player in flight +# Min limit is 0 (not show any objects) +# +# Visibility.Distance.Grey.Unit +# Visibility grey distance for creatures/players (fast changing objects) +# addition to appropriate object type Visibility.Distance.* use in case visibility removing to +# object (except corpse around distences) If D is distance and G is grey distance then object +# make visible if distance to it <= D but make non visible if distance > D+G +# Default: 1 (yard) +# +# Visibility.Distance.Grey.Object +# Visibility grey distance for dynobjects/gameobjects/corpses/creature bodies +# Default: 10 (yards) +# +# +################################################################################################################### + +Visibility.GroupMode = 0 +Visibility.Distance.Creature = 66 +Visibility.Distance.Player = 66 +Visibility.Distance.Object = 66 +Visibility.Distance.InFlight = 66 +Visibility.Distance.Grey.Unit = 1 +Visibility.Distance.Grey.Object = 10 + +################################################################################################################### +# SERVER RATES +# +# Rate.Health +# Rate.Mana +# Rate.Rage.Income +# Rate.Rage.Loss +# Rate.RunicPower.Income +# Rate.RunicPower.Loss +# Rate.Focus +# Rate.Loyalty +# Health and power regeneration and rage income from damage. +# Default: 1 +# +# Rate.Skill.Discovery +# Skill Discovery Rates +# Default: 1 +# +# Rate.Drop.Item.Poor +# Rate.Drop.Item.Normal +# Rate.Drop.Item.Uncommon +# Rate.Drop.Item.Rare +# Rate.Drop.Item.Epic +# Rate.Drop.Item.Legendary +# Rate.Drop.Item.Artifact +# Rate.Drop.Item.Referenced +# Rate.Drop.Money +# Drop rates (items by quality and money) +# Default: 1 +# +# Rate.Drop.Money +# Drop rates +# Default: 1 +# +# Rate.XP.Kill +# Rate.XP.Quest +# Rate.XP.Explore +# XP rates +# Default: 1 +# +# Rate.XP.PastLevel70 +# XP needed per level past 70 (Rates below 1 not recommended) +# Default: 1 +# +# Rate.Rest.InGame +# Rate.Rest.Offline.InTavernOrCity +# Rate.Rest.Offline.InWilderness +# Resting points grow rates (1 - normal, 2 - double rate, 0.5 - half rate, etc) from standard values +# +# Rate.Damage.Fall +# Damage after fall rate. (1 - standard, 2 - double damage, 0.5 - half damage, etc) +# +# Rate.Auction.Time +# Rate.Auction.Deposit +# Rate.Auction.Cut +# Auction rates (auction time, deposit get at auction start, auction cut from price at auction end) +# +# Rate.Honor +# Honor gain rate +# +# Rate.Mining.Amount +# Rate.Mining.Next +# Mining Rates (Mining.Amount changes minimum/maximum usetimes of a deposit, +# Mining.Next changes chance to have next use of a deposit) +# +# Rate.Talent +# Talent Point rates +# Default: 1 +# +# Rate.Reputation.Gain +# Reputation Gain rate +# Default: 1 +# +# Rate.InstanceResetTime +# Multiplier for the number of days in between global raid/heroic instance resets. +# Default: 1 +# +# SkillGain.Crafting +# SkillGain.Defense +# SkillGain.Gathering +# SkillGain.Weapon +# crafting/defense/gathering/weapon skills gain at skill grow (1,2,...) +# Default: 1 +# +# SkillChance.Orange +# SkillChance.Yellow +# SkillChance.Green +# SkillChance.Grey +# Skill chance values (0..100) +# Default: 100-75-25-0 +# +# SkillChance.MiningSteps +# SkillChance.SkinningSteps +# For skinning and Mining chance decrease with skill level. +# Default: 0 - no decrease +# 75 - in 2 times each 75 skill points +# +# DurabilityLossChance.Damage +# Chance lost one from equiped items durability point at damage apply or receive. +# Default: 0.5 (100/0.5 = 200) Each 200 damage apply one from 19 possible equipped items +# +# DurabilityLossChance.Absorb +# Chance lost one from armor items durability point at damage absorb. +# Default: 0.5 (100/0.5 = 200) Each 200 absorbs apply one from 15 possible armor equipped items +# +# DurabilityLossChance.Parry +# Chance lost weapon durability point at parry. +# Default: 0.05 (100/0.05 = 2000) Each 2000 parry attacks main weapon lost point +# +# DurabilityLossChance.Block +# Chance lost sheild durability point at damage block. +# Default: 0.05 (100/0.05 = 2000) Each 2000 partly or full blocked attacks shield lost point +# +# Death.SicknessLevel +# Starting Character start gain sickness at spirit resurrection (1 min) +# Default: 11 +# -10 - character will have full time (10min) sickness at 1 level +# maxplayerlevel+1 - chaarcter will not have sickess at any level +# +# Death.CorpseReclaimDelay.PvP +# Death.CorpseReclaimDelay.PvE +# Enabled/disabled increase corpse reclaim delay at often PvP/PvE deaths +# Default: 1 (enabled) +# 0 (disabled) +# +# Death.Bones.World +# Death.Bones.BattlegroundOrArena +# Enabled/disabled creating bones instead corpse at resurrection (in normal zones/instacnes, or battleground/arenas) +# Default: 1 (enabled) +# 0 (disabled) +# +################################################################################################################### + +Rate.Health = 1 +Rate.Mana = 1 +Rate.Rage.Income = 1 +Rate.Rage.Loss = 1 +Rate.RunicPower.Income = 1 +Rate.RunicPower.Loss = 1 +Rate.Focus = 1 +Rate.Loyalty = 1 +Rate.Skill.Discovery = 1 +Rate.Drop.Item.Poor = 1 +Rate.Drop.Item.Normal = 1 +Rate.Drop.Item.Uncommon = 1 +Rate.Drop.Item.Rare = 1 +Rate.Drop.Item.Epic = 1 +Rate.Drop.Item.Legendary = 1 +Rate.Drop.Item.Artifact = 1 +Rate.Drop.Item.Referenced = 1 +Rate.Drop.Money = 1 +Rate.XP.Kill = 1 +Rate.XP.Quest = 1 +Rate.XP.Explore = 1 +Rate.XP.PastLevel70 = 1 +Rate.Rest.InGame = 1 +Rate.Rest.Offline.InTavernOrCity = 1 +Rate.Rest.Offline.InWilderness = 1 +Rate.Damage.Fall = 1 +Rate.Auction.Time = 1 +Rate.Auction.Deposit = 1 +Rate.Auction.Cut = 1 +Rate.Honor = 1 +Rate.Mining.Amount = 1 +Rate.Mining.Next = 1 +Rate.Talent = 1 +Rate.Reputation.Gain = 1 +Rate.InstanceResetTime = 1 +SkillGain.Crafting = 1 +SkillGain.Defense = 1 +SkillGain.Gathering = 1 +SkillGain.Weapon = 1 +SkillChance.Orange = 100 +SkillChance.Yellow = 75 +SkillChance.Green = 25 +SkillChance.Grey = 0 +SkillChance.MiningSteps = 0 +SkillChance.SkinningSteps = 0 +DurabilityLossChance.Damage = 0.5 +DurabilityLossChance.Absorb = 0.5 +DurabilityLossChance.Parry = 0.05 +DurabilityLossChance.Block = 0.05 +Death.SicknessLevel = 11 +Death.CorpseReclaimDelay.PvP = 1 +Death.CorpseReclaimDelay.PvE = 0 +Death.Bones.World = 1 +Death.Bones.BattlegroundOrArena = 1 + +################################################################################################################### +# +# Rated arena matches config +# +# MaxRatingDifference: the maximum rating difference between two groups in rated matches +# Default: 0 (disable, rating difference is discarded) +# +# RatingDiscardTimer: after the specified milliseconds has passed, +# rating information will be discarded when selecting teams for matches +# also initiates an update by this timer +# Default: 60000 +# +# AutoDistributePoints: set if arena points should be distributed automatically, or by GM command +# Default: 0 (disable) (recommended): use gm command or sql query to distribute the points +# 1 (enable): arena points are distributed automatically +# +# AutoDistributeInterval: how often should the distribution take place +# if automatic distribution is enabled +# in days +# Default: 7 (weekly) +# +# ArenaSeason.ID: current area season id show in client +# Default: 1 +# +# ArenaSeason.InProgress: current area season state +# Default: 1 (active) +# 0 (finished) +# +################################################################################################################### + +Arena.MaxRatingDifference = 0 +Arena.RatingDiscardTimer = 60000 +Arena.AutoDistributePoints = 0 +Arena.AutoDistributeInterval = 7 +Arena.ArenaSeason.ID = 1 +Arena.ArenaSeason.InProgress = 1 + +################################################################################################################### +# +# Battleground config +# +# PrematureFinishTimer: the time to end the bg if there are less than minplayersperteam on one side +# in milliseconds +# Default: 300000 +# 0 - disable +# +################################################################################################################### + +BattleGround.PrematureFinishTimer = 300000 + + +################################################################################################################### +# +# NETWORK CONFIG +# +# Network.Threads +# Number of threads for network, recommend 1 thread per 1000 connections. +# Default: 1 +# +# Network.OutKBuff +# The size of the output kernel buffer used ( SO_SNDBUF socket option, tcp manual ). +# Default: -1 (Use system default setting) +# +# Network.OutUBuff +# Userspace buffer for output. This is amount of memory reserved per each connection. +# Default: 65536 +# +# Network.TcpNoDelay: +# TCP Nagle algorithm setting +# Default: 0 (enable Nagle algorithm, less traffic, more latency) +# 1 (TCP_NO_DELAY, disable Nagle algorithm, more traffic but less latency) +# +################################################################################################################### + +Network.Threads = 1 +Network.OutKBuff = -1 +Network.OutUBuff = 65536 +Network.TcpNodelay = 1 + +################################################################################################################### +# AUCTION HOUSE BOT SETTINGS +# +# AuctionHouseBot.EnableSeller +# Enable/Disable the part of AHBot that puts items up for auction +# Default 0 (disabled) +# +# AuctionHouseBot.EnableBuyer +# Enable/Disable the part of AHBot that buys items from players +# Default 0 (disabled) +# +# Auction House Bot character data +# AuctionHouseBot.Account is the account number (in realmd->account table) of the player you want to run as the auction bot. +# AuctionHouseBot.GUID is the GUID (in characters->characters table) of the player you want to run as the auction bot. +# Default: 0 (Auction House Bot disabled) +# +# AuctionHouseBot.VendorItems +# Include items that can be bought from vendors. +# Default 0 +# +# AuctionHouseBot.LootItems +# Include items that can be looted or fished for. +# Default 1 +# +# AuctionHouseBot.OtherItems +# Include misc. items. +# Default 0 +# +# AuctionHouseBot.Bonding_types +# Indicates which bonding types to allow seller to put up for auction +# No_Bind +# Default 1 +# Bind_When_Picked_Up +# Default 0 +# Bind_When_Equipped +# Default 1 +# Bind_When_Use +# Default 1 +# Bind_Quest_Item +# Default 0 +# +# AuctionHouseBot.ItemsPerCycle +# Number of Items to Add/Remove from the AH during mass operations +# Default 200 +# +# AuctionHouseBot.UseBuyPriceForSeller +# Should the Seller use BuyPrice or SellPrice to determine Bid Prices +# Default 0 (use SellPrice) +# +# AuctionHouseBot.UseBuyPriceForBuyer +# Should the Buyer use BuyPrice or SellPrice to determine Bid Prices +# Default 0 (use SellPrice) +# +# All other settings have been moved to sql +# +################################################################################################################### + +AuctionHouseBot.EnableSeller = 0 +AuctionHouseBot.EnableBuyer = 0 +AuctionHouseBot.Account = 0 +AuctionHouseBot.GUID = 0 +AuctionHouseBot.VendorItems = 0 +AuctionHouseBot.LootItems = 1 +AuctionHouseBot.OtherItems = 0 +AuctionHouseBot.No_Bind = 1 +AuctionHouseBot.Bind_When_Picked_Up = 0 +AuctionHouseBot.Bind_When_Equipped = 1 +AuctionHouseBot.Bind_When_Use = 1 +AuctionHouseBot.Bind_Quest_Item = 0 +AuctionHouseBot.ItemsPerCycle = 200 +AuctionHouseBot.UseBuyPriceForSeller = 0 +AuctionHouseBot.UseBuyPriceForBuyer = 0 + +################################################################################################################### +# CONSOLE AND REMOTE ACCESS +# +# Console.Enable +# Enable console +# Default: 1 - on +# 0 - off +# +# Ra.Enable +# Enable remote console +# Default: 0 - off +# 1 - on +# +# Ra.IP +# Default remote console ip address, use 0.0.0.0 for every address +# +# Ra.Port +# Default remote console port +# +# Ra.MinLevel +# Minimum level that's required to login,3 by default +# +# Ra.Secure +# Kick client on wrong pass +# +################################################################################################################### + +Console.Enable = 1 +Ra.Enable = 0 +Ra.IP = 0.0.0.0 +Ra.Port = 3443 +Ra.MinLevel = 3 +Ra.Secure = 1 + +################################################################################################################### +# CUSTOM SERVER OPTIONS +# +# PlayerStart.AllReputation +# Players will start with most of the high level reputations that are needed for items, mounts etc. +# If there are any reputation faction you want to be added, just tell me. +# +# PlayerStart.AllSpells +# If enabled, players will start with all their class spells (not talents). Useful for instant 70 servers. +# You must import playercreateinfo_spell_custom.sql, it's included in the SQL folder. +# Default: 0 - off +# 1 - on +# +# PlayerStart.MapsExplored +# Players will start with all maps explored if enabled +# +# MusicInBattleground +# If enabled, "L70ETC - Power of the horde" will be played when BG starts ;) +# +# HonorPointsAfterDuel +# The amount of honor points the duel winner will get after a duel. +# Default: 0 - disable +# +# AlwaysMaxWeaponSkill +# Players will automatically gain max weapon/defense skill when logging in, leveling up etc. +# +# PvPToken.Enable +# Enable/disable PvP Token System. Players will get a token after slaying another player that gives honor. +# +# PvPToken.MapAllowType +# Where players can receive the pvp token +# 4 - In all maps +# 3 - In battlegrounds only +# 2 - In FFA areas only (gurubashi arena etc) +# 1 - In battlegrounds AND FFA areas only +# +# PvPToken.ItemID +# The item players will get after killing someone if PvP Token system is enabled. +# Default: 29434 - Badge of justice +# +# PvPToken.ItemCount +# Modify the item ID count - Default: 1 +# +# NoResetTalentsCost +# Enable or disable no cost when reseting talents +# +# ForbiddenMaps +# map ids that users below SEC_GAMEMASTER cannot enter, with delimiter ',' +# Default: "" +# example: "538,90" +# Note that it's HIGHLY DISCOURAGED to forbid starting maps (0, 1, 530)! +# +# ShowKickInWorld +# determines wether a message is broadcasted to the entire server when a player gets kicked +# Default: 0 +# 1 = Enable +# 0 = Disable +# +# RecordUpdateTimeDiffInterval +# record update time diff to the log file +# update diff can be used as a criterion of performance +# diff < 300: good performance +# diff > 600: bad performance, may be caused by high cpu usage +# Default: 60000 (diff is written into log every 60000 ms or 1 minute. +# >0 = Interval +# 0 = Disable +# +# MinRecordUpdateTimeDiff +# only record update time diff which is greater than this value +# +# PlayerStart.String +# If set to anything else than "", this string will be displayed to players when they login +# to a newly created character. +# Default: "" - send no text +# +################################################################################################################### + +PlayerStart.AllReputation = 0 +PlayerStart.AllSpells = 0 +PlayerStart.MapsExplored = 0 +MusicInBattleground = 0 +HonorPointsAfterDuel = 0 +AlwaysMaxWeaponSkill = 0 +PvPToken.Enable = 0 +PvPToken.MapAllowType = 4 +PvPToken.ItemID = 29434 +PvPToken.ItemCount = 1 +NoResetTalentsCost = 0 +ShowKickInWorld = 0 +RecordUpdateTimeDiffInterval = 60000 +MinRecordUpdateTimeDiff = 10 +PlayerStart.String = "" diff --git a/src/trinitycore/TrinityCore.rc b/src/mangosd/mangosd.rc index 4e6510c0407..0acad1e4ba2 100644 --- a/src/trinitycore/TrinityCore.rc +++ b/src/mangosd/mangosd.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/trinitycore/monitor-mangosd b/src/mangosd/monitor-mangosd index a740ae5e8fa..a740ae5e8fa 100644 --- a/src/trinitycore/monitor-mangosd +++ b/src/mangosd/monitor-mangosd diff --git a/src/mangosd/resource.h b/src/mangosd/resource.h new file mode 100644 index 00000000000..7e7d8e4b76f --- /dev/null +++ b/src/mangosd/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by TrinityCore.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/trinitycore/run-mangosd b/src/mangosd/run-mangosd index f307bd9e1ad..f307bd9e1ad 100644 --- a/src/trinitycore/run-mangosd +++ b/src/mangosd/run-mangosd diff --git a/src/realmd/AuthCodes.h b/src/realmd/AuthCodes.h new file mode 100644 index 00000000000..3745c6c6214 --- /dev/null +++ b/src/realmd/AuthCodes.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd +*/ + +#ifndef _AUTHCODES_H +#define _AUTHCODES_H + +enum eAuthResults +{ + REALM_AUTH_SUCCESS = 0x00, + REALM_AUTH_FAILURE = 0x01, ///< Unable to connect + REALM_AUTH_UNKNOWN1 = 0x02, ///< Unable to connect + REALM_AUTH_ACCOUNT_BANNED = 0x03, ///< This <game> account has been closed and is no longer available for use. Please go to <site>/banned.html for further information. + REALM_AUTH_NO_MATCH = 0x04, ///< The information you have entered is not valid. Please check the spelling of the account name and password. If you need help in retrieving a lost or stolen password, see <site> for more information + REALM_AUTH_UNKNOWN2 = 0x05, ///< The information you have entered is not valid. Please check the spelling of the account name and password. If you need help in retrieving a lost or stolen password, see <site> for more information + REALM_AUTH_ACCOUNT_IN_USE = 0x06, ///< This account is already logged into <game>. Please check the spelling and try again. + REALM_AUTH_PREPAID_TIME_LIMIT = 0x07, ///< You have used up your prepaid time for this account. Please purchase more to continue playing + REALM_AUTH_SERVER_FULL = 0x08, ///< Could not log in to <game> at this time. Please try again later. + REALM_AUTH_WRONG_BUILD_NUMBER = 0x09, ///< Unable to validate game version. This may be caused by file corruption or interference of another program. Please visit <site> for more information and possible solutions to this issue. + REALM_AUTH_UPDATE_CLIENT = 0x0a, ///< Downloading + REALM_AUTH_UNKNOWN3 = 0x0b, ///< Unable to connect + REALM_AUTH_ACCOUNT_FREEZED = 0x0c, ///< This <game> account has been temporarily suspended. Please go to <site>/banned.html for further information + REALM_AUTH_UNKNOWN4 = 0x0d, ///< Unable to connect + REALM_AUTH_UNKNOWN5 = 0x0e, ///< Connected. + REALM_AUTH_PARENTAL_CONTROL = 0x0f ///< Access to this account has been blocked by parental controls. Your settings may be changed in your account preferences at <site> +}; + +enum LoginResult +{ + LOGIN_OK = 0x00, + LOGIN_FAILED = 0x01, + LOGIN_FAILED2 = 0x02, + LOGIN_BANNED = 0x03, + LOGIN_UNKNOWN_ACCOUNT = 0x04, + LOGIN_UNKNOWN_ACCOUNT3 = 0x05, + LOGIN_ALREADYONLINE = 0x06, + LOGIN_NOTIME = 0x07, + LOGIN_DBBUSY = 0x08, + LOGIN_BADVERSION = 0x09, + LOGIN_DOWNLOAD_FILE = 0x0A, + LOGIN_FAILED3 = 0x0B, + LOGIN_SUSPENDED = 0x0C, + LOGIN_FAILED4 = 0x0D, + LOGIN_CONNECTED = 0x0E, + LOGIN_PARENTALCONTROL = 0x0F, + LOGIN_LOCKED_ENFORCED = 0x10, +}; + +// we need to stick to 1 version or half of the stuff will work for someone +// others will not and opposite +// will only support WoW, WoW:TBC and WoW:WotLK 3.0.8 client build 9506... + +#define EXPECTED_TRINITY_CLIENT_BUILD {9506, 0} + +#endif diff --git a/src/realmd/AuthSocket.cpp b/src/realmd/AuthSocket.cpp new file mode 100644 index 00000000000..c5c81593737 --- /dev/null +++ b/src/realmd/AuthSocket.cpp @@ -0,0 +1,1094 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd +*/ + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "ByteBuffer.h" +#include "Config/ConfigEnv.h" +#include "Log.h" +#include "RealmList.h" +#include "AuthSocket.h" +#include "AuthCodes.h" +#include <openssl/md5.h> +#include "Auth/Sha1.h" +//#include "Util.h" -- for commented utf8ToUpperOnlyLatin + +extern RealmList m_realmList; + +extern DatabaseType LoginDatabase; + +#define ChunkSize 2048 + +enum eAuthCmd +{ + //AUTH_NO_CMD = 0xFF, + AUTH_LOGON_CHALLENGE = 0x00, + AUTH_LOGON_PROOF = 0x01, + AUTH_RECONNECT_CHALLENGE = 0x02, + AUTH_RECONNECT_PROOF = 0x03, + //update srv =4 + REALM_LIST = 0x10, + XFER_INITIATE = 0x30, + XFER_DATA = 0x31, + XFER_ACCEPT = 0x32, + XFER_RESUME = 0x33, + XFER_CANCEL = 0x34 +}; + +enum eStatus +{ + STATUS_CONNECTED = 0, + STATUS_AUTHED +}; + +// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some paltform +#if defined( __GNUC__ ) +#pragma pack(1) +#else +#pragma pack(push,1) +#endif + +typedef struct AUTH_LOGON_CHALLENGE_C +{ + uint8 cmd; + uint8 error; + uint16 size; + uint8 gamename[4]; + uint8 version1; + uint8 version2; + uint8 version3; + uint16 build; + uint8 platform[4]; + uint8 os[4]; + uint8 country[4]; + uint32 timezone_bias; + uint32 ip; + uint8 I_len; + uint8 I[1]; +} sAuthLogonChallenge_C; + +//typedef sAuthLogonChallenge_C sAuthReconnectChallenge_C; +/* +typedef struct +{ + uint8 cmd; + uint8 error; + uint8 unk2; + uint8 B[32]; + uint8 g_len; + uint8 g[1]; + uint8 N_len; + uint8 N[32]; + uint8 s[32]; + uint8 unk3[16]; +} sAuthLogonChallenge_S; +*/ + +typedef struct AUTH_LOGON_PROOF_C +{ + uint8 cmd; + uint8 A[32]; + uint8 M1[20]; + uint8 crc_hash[20]; + uint8 number_of_keys; + uint8 unk; // Added in 1.12.x client branch +} sAuthLogonProof_C; +/* +typedef struct +{ + uint16 unk1; + uint32 unk2; + uint8 unk3[4]; + uint16 unk4[20]; +} sAuthLogonProofKey_C; +*/ +typedef struct AUTH_LOGON_PROOF_S +{ + uint8 cmd; + uint8 error; + uint8 M2[20]; + uint32 unk1; + uint32 unk2; + uint16 unk3; +} sAuthLogonProof_S; + +typedef struct AUTH_RECONNECT_PROOF_C +{ + uint8 cmd; + uint8 R1[16]; + uint8 R2[20]; + uint8 R3[20]; + uint8 number_of_keys; +} sAuthReconnectProof_C; + +typedef struct XFER_INIT +{ + uint8 cmd; // XFER_INITIATE + uint8 fileNameLen; // strlen(fileName); + uint8 fileName[5]; // fileName[fileNameLen] + uint64 file_size; // file size (bytes) + uint8 md5[MD5_DIGEST_LENGTH]; // MD5 +}XFER_INIT; + +typedef struct XFER_DATA +{ + uint8 opcode; + uint16 data_size; + uint8 data[ChunkSize]; +}XFER_DATA_STRUCT; + +typedef struct AuthHandler +{ + eAuthCmd cmd; + uint32 status; + bool (AuthSocket::*handler)(void); +}AuthHandler; + +// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some paltform +#if defined( __GNUC__ ) +#pragma pack() +#else +#pragma pack(pop) +#endif + +/// Launch a thread to transfer a patch to the client +class PatcherRunnable: public ZThread::Runnable +{ + public: + PatcherRunnable(class AuthSocket *); + void run(); + + private: + AuthSocket * mySocket; +}; + +typedef struct PATCH_INFO +{ + uint8 md5[MD5_DIGEST_LENGTH]; +}PATCH_INFO; + +/// Caches MD5 hash of client patches present on the server +class Patcher +{ + public: + typedef std::map<std::string, PATCH_INFO*> Patches; + ~Patcher(); + Patcher(); + Patches::const_iterator begin() const { return _patches.begin(); } + Patches::const_iterator end() const { return _patches.end(); } + void LoadPatchMD5(char*); + bool GetHash(char * pat,uint8 mymd5[16]); + + private: + void LoadPatchesInfo(); + Patches _patches; +}; + +const AuthHandler table[] = +{ + { AUTH_LOGON_CHALLENGE, STATUS_CONNECTED, &AuthSocket::_HandleLogonChallenge }, + { AUTH_LOGON_PROOF, STATUS_CONNECTED, &AuthSocket::_HandleLogonProof }, + { AUTH_RECONNECT_CHALLENGE, STATUS_CONNECTED, &AuthSocket::_HandleReconnectChallenge}, + { AUTH_RECONNECT_PROOF, STATUS_CONNECTED, &AuthSocket::_HandleReconnectProof }, + { REALM_LIST, STATUS_AUTHED, &AuthSocket::_HandleRealmList }, + { XFER_ACCEPT, STATUS_CONNECTED, &AuthSocket::_HandleXferAccept }, + { XFER_RESUME, STATUS_CONNECTED, &AuthSocket::_HandleXferResume }, + { XFER_CANCEL, STATUS_CONNECTED, &AuthSocket::_HandleXferCancel } +}; + +#define AUTH_TOTAL_COMMANDS sizeof(table)/sizeof(AuthHandler) + +///Holds the MD5 hash of client patches present on the server +Patcher PatchesCache; + +/// Constructor - set the N and g values for SRP6 +AuthSocket::AuthSocket(ISocketHandler &h) : TcpSocket(h) +{ + N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); + g.SetDword(7); + _authed = false; + pPatch = NULL; + + _accountSecurityLevel = SEC_PLAYER; +} + +/// Close patch file descriptor before leaving +AuthSocket::~AuthSocket() +{ + ZThread::Guard<ZThread::Mutex> g(patcherLock); + if(pPatch) + fclose(pPatch); +} + +/// Accept the connection and set the s random value for SRP6 +void AuthSocket::OnAccept() +{ + sLog.outBasic("Accepting connection from '%s:%d'", + GetRemoteAddress().c_str(), GetRemotePort()); + + s.SetRand(s_BYTE_SIZE * 8); +} + +/// Read the packet from the client +void AuthSocket::OnRead() +{ + ///- Read the packet + TcpSocket::OnRead(); + uint8 _cmd; + while (1) + { + if (!ibuf.GetLength()) + return; + + ///- Get the command out of it + ibuf.SoftRead((char *)&_cmd, 1); // UQ1: No longer exists in new net code ??? + //ibuf.Read((char *)&_cmd, 1); + /*char *command = (char *)malloc(1); + + ibuf.Read(command, 1); + + _cmd = (uint8)command;*/ + // assert(0); + size_t i; + + ///- Circle through known commands and call the correct command handler + for (i=0;i<AUTH_TOTAL_COMMANDS; i++) + { + if ((uint8)table[i].cmd == _cmd && + (table[i].status == STATUS_CONNECTED || + (_authed && table[i].status == STATUS_AUTHED))) + { + DEBUG_LOG("[Auth] got data for cmd %u ibuf length %u", (uint32)_cmd, ibuf.GetLength()); + + if (!(*this.*table[i].handler)()) + { + DEBUG_LOG("Command handler failed for cmd %u ibuf length %u", (uint32)_cmd, ibuf.GetLength()); + return; + } + break; + } + } + + ///- Report unknown commands in the debug log + if (i==AUTH_TOTAL_COMMANDS) + { + DEBUG_LOG("[Auth] got unknown packet %u", (uint32)_cmd); + return; + } + } +} + +/// Make the SRP6 calculation from hash in dB +void AuthSocket::_SetVSFields(const std::string& rI) +{ + BigNumber I; + I.SetHexStr(rI.c_str()); + + //In case of leading zeroes in the rI hash, restore them + uint8 mDigest[SHA_DIGEST_LENGTH]; + memset(mDigest,0,SHA_DIGEST_LENGTH); + if (I.GetNumBytes() <= SHA_DIGEST_LENGTH) + memcpy(mDigest,I.AsByteArray(),I.GetNumBytes()); + + std::reverse(mDigest,mDigest+SHA_DIGEST_LENGTH); + + Sha1Hash sha; + sha.UpdateData(s.AsByteArray(), s.GetNumBytes()); + sha.UpdateData(mDigest, SHA_DIGEST_LENGTH); + sha.Finalize(); + BigNumber x; + x.SetBinary(sha.GetDigest(), sha.GetLength()); + v = g.ModExp(x, N); + // No SQL injection (username escaped) + const char *v_hex, *s_hex; + v_hex = v.AsHexStr(); + s_hex = s.AsHexStr(); + LoginDatabase.PExecute("UPDATE account SET v = '%s', s = '%s' WHERE username = '%s'",v_hex,s_hex, _safelogin.c_str() ); + OPENSSL_free((void*)v_hex); + OPENSSL_free((void*)s_hex); +} + +/// Logon Challenge command handler +bool AuthSocket::_HandleLogonChallenge() +{ + DEBUG_LOG("Entering _HandleLogonChallenge"); + if (ibuf.GetLength() < sizeof(sAuthLogonChallenge_C)) + return false; + + ///- Read the first 4 bytes (header) to get the length of the remaining of the packet + std::vector<uint8> buf; + buf.resize(4); + + ibuf.Read((char *)&buf[0], 4); + + EndianConvert(*((uint16*)(buf[0]))); + uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size; + DEBUG_LOG("[AuthChallenge] got header, body is %#04x bytes", remaining); + + if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (ibuf.GetLength() < remaining)) + return false; + + //No big fear of memory outage (size is int16, i.e. < 65536) + buf.resize(remaining + buf.size() + 1); + buf[buf.size() - 1] = 0; + sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0]; + + // BigEndian code, nop in little endian case + // size already converted + EndianConvert(*((uint32*)(&ch->gamename[0]))); + EndianConvert(ch->build); + EndianConvert(*((uint32*)(&ch->platform[0]))); + EndianConvert(*((uint32*)(&ch->os[0]))); + EndianConvert(*((uint32*)(&ch->country[0]))); + EndianConvert(ch->timezone_bias); + EndianConvert(ch->ip); + + ///- Read the remaining of the packet + ibuf.Read((char *)&buf[4], remaining); + DEBUG_LOG("[AuthChallenge] got full packet, %#04x bytes", ch->size); + DEBUG_LOG("[AuthChallenge] name(%d): '%s'", ch->I_len, ch->I); + + ByteBuffer pkt; + + _login = (const char*)ch->I; + _build = ch->build; + + ///- Normalize account name + //utf8ToUpperOnlyLatin(_login); -- client already send account in expected form + + //Escape the user login to avoid further SQL injection + //Memory will be freed on AuthSocket object destruction + _safelogin=_login; + LoginDatabase.escape_string(_safelogin); + + pkt << (uint8) AUTH_LOGON_CHALLENGE; + pkt << (uint8) 0x00; + + ///- Verify that this IP is not in the ip_banned table + // No SQL injection possible (paste the IP address as passed by the socket) + LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + + std::string address = GetRemoteAddress(); + LoginDatabase.escape_string(address); + QueryResult *result = LoginDatabase.PQuery( "SELECT * FROM ip_banned WHERE ip = '%s'",address.c_str()); + if(result) + { + pkt << (uint8)REALM_AUTH_ACCOUNT_BANNED; + sLog.outBasic("[AuthChallenge] Banned ip %s tries to login!",GetRemoteAddress().c_str ()); + delete result; + } + else + { + ///- Get the account details from the account table + // No SQL injection (escaped user name) + + result = LoginDatabase.PQuery("SELECT sha_pass_hash,id,locked,last_ip,gmlevel FROM account WHERE username = '%s'",_safelogin.c_str ()); + if( result ) + { + ///- If the IP is 'locked', check that the player comes indeed from the correct IP address + bool locked = false; + if((*result)[2].GetUInt8() == 1) // if ip is locked + { + DEBUG_LOG("[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), (*result)[3].GetString()); + DEBUG_LOG("[AuthChallenge] Player address is '%s'", GetRemoteAddress().c_str()); + if ( strcmp((*result)[3].GetString(),GetRemoteAddress().c_str()) ) + { + DEBUG_LOG("[AuthChallenge] Account IP differs"); + pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; + locked=true; + } + else + { + DEBUG_LOG("[AuthChallenge] Account IP matches"); + } + } + else + { + DEBUG_LOG("[AuthChallenge] Account '%s' is not locked to ip", _login.c_str()); + } + + if (!locked) + { + //set expired bans to inactive + LoginDatabase.Execute("UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate"); + ///- If the account is banned, reject the logon attempt + QueryResult *banresult = LoginDatabase.PQuery("SELECT bandate,unbandate FROM account_banned WHERE id = %u AND active = 1", (*result)[1].GetUInt32()); + if(banresult) + { + if((*banresult)[0].GetUInt64() == (*banresult)[1].GetUInt64()) + { + pkt << (uint8) REALM_AUTH_ACCOUNT_BANNED; + sLog.outBasic("[AuthChallenge] Banned account %s tries to login!",_login.c_str ()); + } + else + { + pkt << (uint8) REALM_AUTH_ACCOUNT_FREEZED; + sLog.outBasic("[AuthChallenge] Temporarily banned account %s tries to login!",_login.c_str ()); + } + + delete banresult; + } + else + { + ///- Get the password from the account table, upper it, and make the SRP6 calculation + std::string rI = (*result)[0].GetCppString(); + _SetVSFields(rI); + + b.SetRand(19 * 8); + BigNumber gmod=g.ModExp(b, N); + B = ((v * 3) + gmod) % N; + + ASSERT(gmod.GetNumBytes() <= 32); + + BigNumber unk3; + unk3.SetRand(16*8); + + ///- Fill the response packet with the result + pkt << (uint8)REALM_AUTH_SUCCESS; + + // B may be calculated < 32B so we force minnimal length to 32B + pkt.append(B.AsByteArray(32), 32); // 32 bytes + pkt << (uint8)1; + pkt.append(g.AsByteArray(), 1); + pkt << (uint8)32; + pkt.append(N.AsByteArray(), 32); + pkt.append(s.AsByteArray(), s.GetNumBytes()); // 32 bytes + pkt.append(unk3.AsByteArray(), 16); + pkt << (uint8)0; // Added in 1.12.x client branch + + uint8 secLevel = (*result)[4].GetUInt8(); + _accountSecurityLevel = secLevel <= SEC_ADMINISTRATOR ? AccountTypes(secLevel) : SEC_ADMINISTRATOR; + + _localizationName.resize(4); + for(int i = 0; i <4; ++i) + _localizationName[i] = ch->country[4-i-1]; + + sLog.outBasic("[AuthChallenge] account %s is using '%c%c%c%c' locale (%u)", _login.c_str (), ch->country[3],ch->country[2],ch->country[1],ch->country[0], GetLocaleByName(_localizationName)); + } + } + delete result; + } + else //no account + { + pkt<< (uint8) REALM_AUTH_NO_MATCH; + } + } + SendBuf((char const*)pkt.contents(), pkt.size()); + return true; +} + +/// Logon Proof command handler +bool AuthSocket::_HandleLogonProof() +{ + DEBUG_LOG("Entering _HandleLogonProof"); + ///- Read the packet + if (ibuf.GetLength() < sizeof(sAuthLogonProof_C)) + return false; + sAuthLogonProof_C lp; + ibuf.Read((char *)&lp, sizeof(sAuthLogonProof_C)); + + ///- Check if the client has one of the expected version numbers + bool valid_version=false; + int accepted_versions[]=EXPECTED_TRINITY_CLIENT_BUILD; + for(int i=0;accepted_versions[i];i++) + { + if(_build==accepted_versions[i]) + { + valid_version=true; + break; + } + } + + /// <ul><li> If the client has no valid version + if(!valid_version) + { + ///- Check if we have the apropriate patch on the disk + + // 24 = len("./patches/65535enGB.mpq")+1 + char tmp[24]; + // No buffer overflow (fixed length of arguments) + sprintf(tmp,"./patches/%d%s.mpq",_build, _localizationName.c_str()); + // This will be closed at the destruction of the AuthSocket (client deconnection) + FILE *pFile=fopen(tmp,"rb"); + + if(!pFile) + { + ByteBuffer pkt; + pkt << (uint8) AUTH_LOGON_CHALLENGE; + pkt << (uint8) 0x00; + pkt << (uint8) REALM_AUTH_WRONG_BUILD_NUMBER; + DEBUG_LOG("[AuthChallenge] %u is not a valid client version!", _build); + DEBUG_LOG("[AuthChallenge] Patch %s not found",tmp); + SendBuf((char const*)pkt.contents(), pkt.size()); + return true; + } + else // have patch + { + pPatch=pFile; + XFER_INIT xferh; + + ///- Get the MD5 hash of the patch file (get it from preloaded Patcher cache or calculate it) + if(PatchesCache.GetHash(tmp,(uint8*)&xferh.md5)) + { + DEBUG_LOG("\n[AuthChallenge] Found precached patch info for patch %s",tmp); + } + else + { //calculate patch md5 + printf("\n[AuthChallenge] Patch info for %s was not cached.",tmp); + PatchesCache.LoadPatchMD5(tmp); + PatchesCache.GetHash(tmp,(uint8*)&xferh.md5); + } + + ///- Send a packet to the client with the file length and MD5 hash + uint8 data[2]={AUTH_LOGON_PROOF,REALM_AUTH_UPDATE_CLIENT}; + SendBuf((const char*)data,sizeof(data)); + + memcpy(&xferh,"0\x05Patch",7); + xferh.cmd=XFER_INITIATE; + fseek(pPatch,0,SEEK_END); + xferh.file_size=ftell(pPatch); + + SendBuf((const char*)&xferh,sizeof(xferh)); + return true; + } + } + /// </ul> + + ///- Continue the SRP6 calculation based on data received from the client + BigNumber A; + A.SetBinary(lp.A, 32); + + Sha1Hash sha; + sha.UpdateBigNumbers(&A, &B, NULL); + sha.Finalize(); + BigNumber u; + u.SetBinary(sha.GetDigest(), 20); + BigNumber S = (A * (v.ModExp(u, N))).ModExp(b, N); + + uint8 t[32]; + uint8 t1[16]; + uint8 vK[40]; + memcpy(t, S.AsByteArray(), 32); + for (int i = 0; i < 16; i++) + { + t1[i] = t[i*2]; + } + sha.Initialize(); + sha.UpdateData(t1, 16); + sha.Finalize(); + for (int i = 0; i < 20; i++) + { + vK[i*2] = sha.GetDigest()[i]; + } + for (int i = 0; i < 16; i++) + { + t1[i] = t[i*2+1]; + } + sha.Initialize(); + sha.UpdateData(t1, 16); + sha.Finalize(); + for (int i = 0; i < 20; i++) + { + vK[i*2+1] = sha.GetDigest()[i]; + } + K.SetBinary(vK, 40); + + uint8 hash[20]; + + sha.Initialize(); + sha.UpdateBigNumbers(&N, NULL); + sha.Finalize(); + memcpy(hash, sha.GetDigest(), 20); + sha.Initialize(); + sha.UpdateBigNumbers(&g, NULL); + sha.Finalize(); + for (int i = 0; i < 20; i++) + { + hash[i] ^= sha.GetDigest()[i]; + } + BigNumber t3; + t3.SetBinary(hash, 20); + + sha.Initialize(); + sha.UpdateData(_login); + sha.Finalize(); + uint8 t4[SHA_DIGEST_LENGTH]; + memcpy(t4, sha.GetDigest(), SHA_DIGEST_LENGTH); + + sha.Initialize(); + sha.UpdateBigNumbers(&t3, NULL); + sha.UpdateData(t4, SHA_DIGEST_LENGTH); + sha.UpdateBigNumbers(&s, &A, &B, &K, NULL); + sha.Finalize(); + BigNumber M; + M.SetBinary(sha.GetDigest(), 20); + + ///- Check if SRP6 results match (password is correct), else send an error + if (!memcmp(M.AsByteArray(), lp.M1, 20)) + { + sLog.outBasic("User '%s' successfully authenticated", _login.c_str()); + + ///- Update the sessionkey, last_ip, last login time and reset number of failed logins in the account table for this account + // No SQL injection (escaped user name) and IP address as received by socket + const char* K_hex = K.AsHexStr(); + LoginDatabase.PExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = '%u', failed_logins = 0 WHERE username = '%s'", K_hex, GetRemoteAddress().c_str(), GetLocaleByName(_localizationName), _safelogin.c_str() ); + OPENSSL_free((void*)K_hex); + + ///- Finish SRP6 and send the final result to the client + sha.Initialize(); + sha.UpdateBigNumbers(&A, &M, &K, NULL); + sha.Finalize(); + + sAuthLogonProof_S proof; + memcpy(proof.M2, sha.GetDigest(), 20); + proof.cmd = AUTH_LOGON_PROOF; + proof.error = 0; + proof.unk1 = 0x00800000; + proof.unk2 = 0x00; + proof.unk3 = 0x00; + + SendBuf((char *)&proof, sizeof(proof)); + + ///- Set _authed to true! + _authed = true; + } + else + { + char data[4]={AUTH_LOGON_PROOF,REALM_AUTH_NO_MATCH,3,0}; + SendBuf(data,sizeof(data)); + sLog.outBasic("[AuthChallenge] account %s tried to login with wrong password!",_login.c_str ()); + + uint32 MaxWrongPassCount = sConfig.GetIntDefault("WrongPass.MaxCount", 0); + if(MaxWrongPassCount > 0) + { + //Increment number of failed logins by one and if it reaches the limit temporarily ban that account or IP + LoginDatabase.PExecute("UPDATE account SET failed_logins = failed_logins + 1 WHERE username = '%s'",_safelogin.c_str()); + + if(QueryResult *loginfail = LoginDatabase.PQuery("SELECT id, failed_logins FROM account WHERE username = '%s'", _safelogin.c_str())) + { + Field* fields = loginfail->Fetch(); + uint32 failed_logins = fields[1].GetUInt32(); + + if( failed_logins >= MaxWrongPassCount ) + { + uint32 WrongPassBanTime = sConfig.GetIntDefault("WrongPass.BanTime", 600); + bool WrongPassBanType = sConfig.GetBoolDefault("WrongPass.BanType", false); + + if(WrongPassBanType) + { + uint32 acc_id = fields[0].GetUInt32(); + LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban',1)", + acc_id, WrongPassBanTime); + sLog.outBasic("[AuthChallenge] account %s got banned for '%u' seconds because it failed to authenticate '%u' times", + _login.c_str(), WrongPassBanTime, failed_logins); + } + else + { + std::string current_ip = GetRemoteAddress(); + LoginDatabase.escape_string(current_ip); + LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+'%u','Trinity realmd','Failed login autoban')", + current_ip.c_str(), WrongPassBanTime); + sLog.outBasic("[AuthChallenge] IP %s got banned for '%u' seconds because account %s failed to authenticate '%u' times", + current_ip.c_str(), WrongPassBanTime, _login.c_str(), failed_logins); + } + } + delete loginfail; + } + } + } + return true; +} + +/// Reconnect Challenge command handler +bool AuthSocket::_HandleReconnectChallenge() +{ + DEBUG_LOG("Entering _HandleReconnectChallenge"); + if (ibuf.GetLength() < sizeof(sAuthLogonChallenge_C)) + return false; + + ///- Read the first 4 bytes (header) to get the length of the remaining of the packet + std::vector<uint8> buf; + buf.resize(4); + + ibuf.Read((char *)&buf[0], 4); + + EndianConvert(*((uint16*)(buf[0]))); + uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size; + DEBUG_LOG("[ReconnectChallenge] got header, body is %#04x bytes", remaining); + + if ((remaining < sizeof(sAuthLogonChallenge_C) - buf.size()) || (ibuf.GetLength() < remaining)) + return false; + + //No big fear of memory outage (size is int16, i.e. < 65536) + buf.resize(remaining + buf.size() + 1); + buf[buf.size() - 1] = 0; + sAuthLogonChallenge_C *ch = (sAuthLogonChallenge_C*)&buf[0]; + + ///- Read the remaining of the packet + ibuf.Read((char *)&buf[4], remaining); + DEBUG_LOG("[ReconnectChallenge] got full packet, %#04x bytes", ch->size); + DEBUG_LOG("[ReconnectChallenge] name(%d): '%s'", ch->I_len, ch->I); + + _login = (const char*)ch->I; + _safelogin = _login; + + QueryResult *result = LoginDatabase.PQuery ("SELECT sessionkey FROM account WHERE username = '%s'", _safelogin.c_str ()); + + // Stop if the account is not found + if (!result) + { + sLog.outError("[ERROR] user %s tried to login and we cannot find his session key in the database.", _login.c_str()); + SetCloseAndDelete(); + return false; + } + + Field* fields = result->Fetch (); + K.SetHexStr (fields[0].GetString ()); + delete result; + + ///- Sending response + ByteBuffer pkt; + pkt << (uint8) AUTH_RECONNECT_CHALLENGE; + pkt << (uint8) 0x00; + _reconnectProof.SetRand(16*8); + pkt.append(_reconnectProof.AsByteBuffer()); // 16 bytes random + pkt << (uint64) 0x00 << (uint64) 0x00; // 16 bytes zeros + SendBuf((char const*)pkt.contents(), pkt.size()); + return true; +} + +/// Reconnect Proof command handler +bool AuthSocket::_HandleReconnectProof() +{ + DEBUG_LOG("Entering _HandleReconnectProof"); + ///- Read the packet + if (ibuf.GetLength() < sizeof(sAuthReconnectProof_C)) + return false; + if (_login.empty() || !_reconnectProof.GetNumBytes() || !K.GetNumBytes()) + return false; + sAuthReconnectProof_C lp; + ibuf.Read((char *)&lp, sizeof(sAuthReconnectProof_C)); + + BigNumber t1; + t1.SetBinary(lp.R1, 16); + + Sha1Hash sha; + sha.Initialize(); + sha.UpdateData(_login); + sha.UpdateBigNumbers(&t1, &_reconnectProof, &K, NULL); + sha.Finalize(); + + if (!memcmp(sha.GetDigest(), lp.R2, SHA_DIGEST_LENGTH)) + { + ///- Sending response + ByteBuffer pkt; + pkt << (uint8) AUTH_RECONNECT_PROOF; + pkt << (uint8) 0x00; + pkt << (uint16) 0x00; // 2 bytes zeros + SendBuf((char const*)pkt.contents(), pkt.size()); + + ///- Set _authed to true! + _authed = true; + + return true; + } + else + { + sLog.outError("[ERROR] user %s tried to login, but session invalid.", _login.c_str()); + SetCloseAndDelete(); + return false; + } +} + +/// %Realm List command handler +bool AuthSocket::_HandleRealmList() +{ + DEBUG_LOG("Entering _HandleRealmList"); + if (ibuf.GetLength() < 5) + return false; + + ibuf.Remove(5); + + ///- Get the user id (else close the connection) + // No SQL injection (escaped user name) + + QueryResult *result = LoginDatabase.PQuery("SELECT id,sha_pass_hash FROM account WHERE username = '%s'",_safelogin.c_str()); + if(!result) + { + sLog.outError("[ERROR] user %s tried to login and we cannot find him in the database.",_login.c_str()); + SetCloseAndDelete(); + return false; + } + + uint32 id = (*result)[0].GetUInt32(); + std::string rI = (*result)[1].GetCppString(); + delete result; + + ///- Update realm list if need + m_realmList.UpdateIfNeed(); + + ///- Circle through realms in the RealmList and construct the return packet (including # of user characters in each realm) + ByteBuffer pkt; + pkt << (uint32) 0; + pkt << (uint16) m_realmList.size(); + RealmList::RealmMap::const_iterator i; + for( i = m_realmList.begin(); i != m_realmList.end(); i++ ) + { + uint8 AmountOfCharacters; + + // No SQL injection. id of realm is controlled by the database. + result = LoginDatabase.PQuery( "SELECT numchars FROM realmcharacters WHERE realmid = '%d' AND acctid='%u'",i->second.m_ID,id); + if( result ) + { + Field *fields = result->Fetch(); + AmountOfCharacters = fields[0].GetUInt8(); + delete result; + } + else + AmountOfCharacters = 0; + + uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; + + pkt << i->second.icon; // realm type + pkt << lock; // if 1, then realm locked + pkt << i->second.color; // if 2, then realm is offline + pkt << i->first; + pkt << i->second.address; + pkt << i->second.populationLevel; + pkt << AmountOfCharacters; + pkt << i->second.timezone; // realm category + pkt << (uint8) 0x2C; // unk, may be realm number/id? + } + pkt << (uint8) 0x10; + pkt << (uint8) 0x00; + + ByteBuffer hdr; + hdr << (uint8) REALM_LIST; + hdr << (uint16)pkt.size(); + hdr.append(pkt); + + SendBuf((char const*)hdr.contents(), hdr.size()); + + // Set check field before possible relogin to realm + _SetVSFields(rI); + return true; +} + +/// Resume patch transfer +bool AuthSocket::_HandleXferResume() +{ + DEBUG_LOG("Entering _HandleXferResume"); + ///- Check packet length and patch existence + if (ibuf.GetLength()<9 || !pPatch) + { + sLog.outError("Error while resuming patch transfer (wrong packet)"); + return false; + } + + ///- Launch a PatcherRunnable thread starting at given patch file offset + uint64 start; + ibuf.Remove(1); + ibuf.Read((char*)&start,sizeof(start)); + fseek(pPatch,start,0); + + ZThread::Thread u(new PatcherRunnable(this)); + return true; +} + +/// Cancel patch transfer +bool AuthSocket::_HandleXferCancel() +{ + DEBUG_LOG("Entering _HandleXferCancel"); + + ///- Close and delete the socket + ibuf.Remove(1); //clear input buffer + + //ZThread::Thread::sleep(15); + SetCloseAndDelete(); + + return true; +} + +/// Accept patch transfer +bool AuthSocket::_HandleXferAccept() +{ + DEBUG_LOG("Entering _HandleXferAccept"); + + ///- Check packet length and patch existence + if (!pPatch) + { + sLog.outError("Error while accepting patch transfer (wrong packet)"); + return false; + } + + ///- Launch a PatcherRunnable thread, starting at the begining of the patch file + ibuf.Remove(1); //clear input buffer + fseek(pPatch,0,0); + + ZThread::Thread u(new PatcherRunnable(this)); + + return true; +} + +/// Check if there is lag on the connection to the client +bool AuthSocket::IsLag() +{ + return (TCP_BUFSIZE_READ-GetOutputLength()< 2*ChunkSize); +} + +PatcherRunnable::PatcherRunnable(class AuthSocket * as) +{ + mySocket=as; +} + +/// Send content of patch file to the client +void PatcherRunnable::run() +{ + ZThread::Guard<ZThread::Mutex> g(mySocket->patcherLock); + XFER_DATA_STRUCT xfdata; + xfdata.opcode = XFER_DATA; + + while(!feof(mySocket->pPatch) && mySocket->Ready()) + { + ///- Wait until output buffer is reasonably empty + while(mySocket->Ready() && mySocket->IsLag()) + { + ZThread::Thread::sleep(1); + } + ///- And send content of the patch file to the client + xfdata.data_size=fread(&xfdata.data,1,ChunkSize,mySocket->pPatch); + mySocket->SendBuf((const char*)&xfdata,xfdata.data_size +(sizeof(XFER_DATA_STRUCT)-ChunkSize)); + } +} + +/// Preload MD5 hashes of existing patch files on server +#ifndef _WIN32 +#include <dirent.h> +#include <errno.h> +void Patcher::LoadPatchesInfo() +{ + DIR * dirp; + //int errno; + struct dirent * dp; + dirp = opendir("./patches/"); + if(!dirp) + return; + while (dirp) + { + errno = 0; + if ((dp = readdir(dirp)) != NULL) + { + int l=strlen(dp->d_name); + if(l<8)continue; + if(!memcmp(&dp->d_name[l-4],".mpq",4)) + LoadPatchMD5(dp->d_name); + } + else + { + if(errno != 0) + { + closedir(dirp); + return; + } + break; + } + } + + if(dirp) + closedir(dirp); +} + +#else +void Patcher::LoadPatchesInfo() +{ + WIN32_FIND_DATA fil; + HANDLE hFil=FindFirstFile("./patches/*.mpq",&fil); + if(hFil==INVALID_HANDLE_VALUE) + return; //no patches were found + + do + { + LoadPatchMD5(fil.cFileName); + } + while(FindNextFile(hFil,&fil)); +} +#endif + +/// Calculate and store MD5 hash for a given patch file +void Patcher::LoadPatchMD5(char * szFileName) +{ + ///- Try to open the patch file + std::string path = "./patches/"; + path += szFileName; + FILE * pPatch=fopen(path.c_str(),"rb"); + sLog.outDebug("Loading patch info from %s\n",path.c_str()); + if(!pPatch) + { + sLog.outError("Error loading patch %s\n",path.c_str()); + return; + } + + ///- Calculate the MD5 hash + MD5_CTX ctx; + MD5_Init(&ctx); + uint8* buf = new uint8[512*1024]; + + while (!feof(pPatch)) + { + size_t read = fread(buf, 1, 512*1024, pPatch); + MD5_Update(&ctx, buf, read); + } + delete [] buf; + fclose(pPatch); + + ///- Store the result in the internal patch hash map + _patches[path] = new PATCH_INFO; + MD5_Final((uint8 *)&_patches[path]->md5 , &ctx); +} + +/// Get cached MD5 hash for a given patch file +bool Patcher::GetHash(char * pat,uint8 mymd5[16]) +{ + for( Patches::iterator i = _patches.begin(); i != _patches.end(); i++ ) + if(!stricmp(pat,i->first.c_str () )) + { + memcpy(mymd5,i->second->md5,16); + return true; + } + + return false; +} + +/// Launch the patch hashing mechanism on object creation +Patcher::Patcher() +{ + LoadPatchesInfo(); +} + +/// Empty and delete the patch map on termination +Patcher::~Patcher() +{ + for(Patches::iterator i = _patches.begin(); i != _patches.end(); i++ ) + delete i->second; +} diff --git a/src/trinityrealm/AuthSocket.h b/src/realmd/AuthSocket.h index f704283c215..3cae54c7789 100644 --- a/src/trinityrealm/AuthSocket.h +++ b/src/realmd/AuthSocket.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/realmd/CMakeLists.txt b/src/realmd/CMakeLists.txt new file mode 100644 index 00000000000..ab03c3143a5 --- /dev/null +++ b/src/realmd/CMakeLists.txt @@ -0,0 +1,45 @@ +########### next target ############### + +SET(trinity-realm_SRCS +AuthCodes.h +AuthSocket.cpp +AuthSocket.h +Main.cpp +RealmList.cpp +RealmList.h +) + +add_executable(trinity-realm ${trinity-realm_SRCS}) +add_definitions( +-D_TRINITY_REALM_CONFIG='"${CONF_DIR}/trinityrealm.conf"' +) +IF (DO_MYSQL) + #SET_TARGET_PROPERTIES(mangos-realmd PROPERTIES LINK_FLAGS ${MYSQL_LIBS}) + SET_TARGET_PROPERTIES(trinity-realm PROPERTIES LINK_FLAGS "-pthread") +ENDIF(DO_MYSQL) +IF (DO_POSTGRE) + SET_TARGET_PROPERTIES(trinity-realmd PROPERTIES LINK_FLAGS ${POSTGRE_LIBS}) +ENDIF(DO_POSTGRE) + + +target_link_libraries( +trinity-realm +shared +trinityframework +trinitysockets +trinitydatabase +trinityauth +trinityconfig +ZThread +zlib +${SSLLIB} +${MYSQL_LIBRARIES} +) + +install(TARGETS trinity-realm DESTINATION bin) + + +########### install files ############### + +install(FILES realmd.conf.dist.in DESTINATION etc) + diff --git a/src/realmd/Main.cpp b/src/realmd/Main.cpp new file mode 100644 index 00000000000..f36558e6fba --- /dev/null +++ b/src/realmd/Main.cpp @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup realmd Realm Daemon +/// @{ +/// \file + +#include "Common.h" +#include "Database/DatabaseEnv.h" +#include "RealmList.h" + +#include "Config/ConfigEnv.h" +#include "Log.h" +#include "sockets/ListenSocket.h" +#include "AuthSocket.h" +#include "SystemConfig.h" +#include "Util.h" + +// Format is YYYYMMDDRR where RR is the change in the conf file +// for that day. +#ifndef _REALMDCONFVERSION +# define _REALMDCONFVERSION 2007062001 +#endif + +#ifndef _TRINITY_REALM_CONFIG +# define _TRINITY_REALM_CONFIG "TrinityRealm.conf" +#endif //_TRINITY_REALM_CONFIG + +#ifdef WIN32 +#include "ServiceWin32.h" +char serviceName[] = "TrinityRealm"; +char serviceLongName[] = "Trinity realm service"; +char serviceDescription[] = "Massive Network Game Object Server"; +/* + * -1 - not in service mode + * 0 - stopped + * 1 - running + * 2 - paused + */ +int m_ServiceStatus = -1; +#endif + +bool StartDB(std::string &dbstring); +void UnhookSignals(); +void HookSignals(); + +bool stopEvent = false; ///< Setting it to true stops the server +RealmList m_realmList; ///< Holds the list of realms for this server + +DatabaseType LoginDatabase; ///< Accessor to the realm server database + +/// Print out the usage string for this program on the console. +void usage(const char *prog) +{ + sLog.outString("Usage: \n %s [<options>]\n" + " -c config_file use config_file as configuration file\n\r" + #ifdef WIN32 + " Running as service functions:\n\r" + " --service run as service\n\r" + " -s install install service\n\r" + " -s uninstall uninstall service\n\r" + #endif + ,prog); +} + +/// Launch the realm server +extern int main(int argc, char **argv) +{ + ///- Command line parsing to get the configuration file name + char const* cfg_file = _TRINITY_REALM_CONFIG; + int c=1; + while( c < argc ) + { + if( strcmp(argv[c],"-c") == 0) + { + if( ++c >= argc ) + { + sLog.outError("Runtime-Error: -c option requires an input argument"); + usage(argv[0]); + return 1; + } + else + cfg_file = argv[c]; + } + + #ifdef WIN32 + //////////// + //Services// + //////////// + if( strcmp(argv[c],"-s") == 0) + { + if( ++c >= argc ) + { + sLog.outError("Runtime-Error: -s option requires an input argument"); + usage(argv[0]); + return 1; + } + if( strcmp(argv[c],"install") == 0) + { + if (WinServiceInstall()) + sLog.outString("Installing service"); + return 1; + } + else if( strcmp(argv[c],"uninstall") == 0) + { + if(WinServiceUninstall()) + sLog.outString("Uninstalling service"); + return 1; + } + else + { + sLog.outError("Runtime-Error: unsupported option %s",argv[c]); + usage(argv[0]); + return 1; + } + } + if( strcmp(argv[c],"--service") == 0) + { + WinServiceRun(); + } + //// + #endif + ++c; + } + + if (!sConfig.SetSource(cfg_file)) + { + sLog.outError("Could not find configuration file %s.", cfg_file); + return 1; + } + sLog.outString("Using configuration file %s.", cfg_file); + + ///- Check the version of the configuration file + uint32 confVersion = sConfig.GetIntDefault("ConfVersion", 0); + if (confVersion < _REALMDCONFVERSION) + { + sLog.outError("*****************************************************************************"); + sLog.outError(" WARNING: Your trinityrealm.conf version indicates your conf file is out of date!"); + sLog.outError(" Please check for updates, as your current default values may cause"); + sLog.outError(" strange behavior."); + sLog.outError("*****************************************************************************"); + clock_t pause = 3000 + clock(); + + while (pause > clock()) {} + } + + sLog.outString( "%s (realm-daemon)", _FULLVERSION ); + sLog.outString( "<Ctrl-C> to stop.\n" ); + + /// realmd PID file creation + std::string pidfile = sConfig.GetStringDefault("PidFile", ""); + if(!pidfile.empty()) + { + uint32 pid = CreatePIDFile(pidfile); + if( !pid ) + { + sLog.outError( "Cannot create PID file %s.\n", pidfile.c_str() ); + return 1; + } + + sLog.outString( "Daemon PID: %u\n", pid ); + } + + ///- Initialize the database connection + std::string dbstring; + if(!StartDB(dbstring)) + return 1; + + ///- Get the list of realms for the server + m_realmList.Initialize(sConfig.GetIntDefault("RealmsStateUpdateDelay", 20)); + if (m_realmList.size() == 0) + { + sLog.outError("No valid realms specified."); + return 1; + } + + ///- Launch the listening network socket + port_t rmport = sConfig.GetIntDefault( "RealmServerPort", DEFAULT_REALMSERVER_PORT ); + std::string bind_ip = sConfig.GetStringDefault("BindIP", "0.0.0.0"); + + SocketHandler h; + ListenSocket<AuthSocket> authListenSocket(h); + if ( authListenSocket.Bind(bind_ip.c_str(),rmport)) + { + sLog.outError( "Trinity realm can not bind to %s:%d",bind_ip.c_str(), rmport ); + return 1; + } + + h.Add(&authListenSocket); + + ///- Catch termination signals + HookSignals(); + + ///- Handle affinity for multiple processors and process priority on Windows + #ifdef WIN32 + { + HANDLE hProcess = GetCurrentProcess(); + + uint32 Aff = sConfig.GetIntDefault("UseProcessors", 0); + if(Aff > 0) + { + ULONG_PTR appAff; + ULONG_PTR sysAff; + + if(GetProcessAffinityMask(hProcess,&appAff,&sysAff)) + { + ULONG_PTR curAff = Aff & appAff; // remove non accessible processors + + if(!curAff ) + { + sLog.outError("Processors marked in UseProcessors bitmask (hex) %x not accessible for realmd. Accessible processors bitmask (hex): %x",Aff,appAff); + } + else + { + if(SetProcessAffinityMask(hProcess,curAff)) + sLog.outString("Using processors (bitmask, hex): %x", curAff); + else + sLog.outError("Can't set used processors (hex): %x", curAff); + } + } + sLog.outString(); + } + + bool Prio = sConfig.GetBoolDefault("ProcessPriority", false); + + if(Prio) + { + if(SetPriorityClass(hProcess,HIGH_PRIORITY_CLASS)) + sLog.outString("TrinityRealm process priority class set to HIGH"); + else + sLog.outError("ERROR: Can't set realmd process priority class."); + sLog.outString(); + } + } + #endif + + // maximum counter for next ping + uint32 numLoops = (sConfig.GetIntDefault( "MaxPingTime", 30 ) * (MINUTE * 1000000 / 100000)); + uint32 loopCounter = 0; + + ///- Wait for termination signal + while (!stopEvent) + { + + h.Select(0, 100000); + + if( (++loopCounter) == numLoops ) + { + loopCounter = 0; + sLog.outDetail("Ping MySQL to keep connection alive"); + delete LoginDatabase.Query("SELECT 1 FROM realmlist LIMIT 1"); + } +#ifdef WIN32 + if (m_ServiceStatus == 0) stopEvent = true; + while (m_ServiceStatus == 2) Sleep(1000); +#endif + } + + ///- Wait for the delay thread to exit + LoginDatabase.HaltDelayThread(); + + ///- Remove signal handling before leaving + UnhookSignals(); + + sLog.outString( "Halting process..." ); + return 0; +} + +/// Handle termination signals +/** Put the global variable stopEvent to 'true' if a termination signal is caught **/ +void OnSignal(int s) +{ + switch (s) + { + case SIGINT: + case SIGTERM: + stopEvent = true; + break; + #ifdef _WIN32 + case SIGBREAK: + stopEvent = true; + break; + #endif + } + + signal(s, OnSignal); +} + +/// Initialize connection to the database +bool StartDB(std::string &dbstring) +{ + if(!sConfig.GetString("LoginDatabaseInfo", &dbstring)) + { + sLog.outError("Database not specified"); + return false; + } + + sLog.outString("Database: %s", dbstring.c_str() ); + if(!LoginDatabase.Initialize(dbstring.c_str())) + { + sLog.outError("Cannot connect to database"); + return false; + } + + return true; +} + +/// Define hook 'OnSignal' for all termination signals +void HookSignals() +{ + signal(SIGINT, OnSignal); + signal(SIGTERM, OnSignal); + #ifdef _WIN32 + signal(SIGBREAK, OnSignal); + #endif +} + +/// Unhook the signals before leaving +void UnhookSignals() +{ + signal(SIGINT, 0); + signal(SIGTERM, 0); + #ifdef _WIN32 + signal(SIGBREAK, 0); + #endif +} + +/// @} diff --git a/src/realmd/Makefile.am b/src/realmd/Makefile.am new file mode 100644 index 00000000000..a14b50c847a --- /dev/null +++ b/src/realmd/Makefile.am @@ -0,0 +1,59 @@ +# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> +# +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = $(TRINI_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir)/../../dep/include -I$(srcdir)/../framework -I$(srcdir)/../shared -I$(srcdir) -DSYSCONFDIR=\"$(sysconfdir)/\" + +## Build realm list daemon as standalone program +bin_PROGRAMS = trinity-realmd +trinity_realmd_SOURCES = \ + AuthCodes.h \ + AuthSocket.cpp \ + AuthSocket.h \ + Main.cpp \ + RealmList.cpp \ + RealmList.h + +## Link realm list daemon against the shared library +trinity_realmd_LDADD = ../shared/Database/libmangosdatabase.a ../shared/Config/libmangosconfig.a ../shared/Auth/libmangosauth.a ../shared/libmangosshared.a ../framework/libmangosframework.a ../../dep/src/sockets/libmangossockets.a ../../dep/src/zthread/libZThread.la +trinity_realmd_LDFLAGS = -L../../dep/src/sockets -L../../dep/src/zthread -L$(libdir) $(TRINI_LIBS) + +## Additional files to include when running 'make dist' +# Include realm list daemon configuration +EXTRA_DIST = \ + realmd.conf.dist + +## Additional files to install +sysconf_DATA = \ + realmd.conf.dist + +install-data-hook: + @list='$(sysconf_DATA)'; for p in $$list; do \ + dest=`echo $$p | sed -e s/.dist//`; \ + if test -f $(DESTDIR)$(sysconfdir)/$$dest; then \ + echo "$@ will not overwrite existing $(DESTDIR)$(sysconfdir)/$$dest"; \ + else \ + echo " $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest"; \ + $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest; \ + fi; \ + done + +clean-local: + rm -f $(sysconf_DATA) diff --git a/src/realmd/RealmList.cpp b/src/realmd/RealmList.cpp new file mode 100644 index 00000000000..936f7bcd703 --- /dev/null +++ b/src/realmd/RealmList.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** \file + \ingroup realmd +*/ + +#include "Common.h" +#include "RealmList.h" +#include "Policies/SingletonImp.h" +#include "Database/DatabaseEnv.h" + +INSTANTIATE_SINGLETON_1( RealmList ); + +extern DatabaseType LoginDatabase; + +RealmList::RealmList( ) : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)) +{ +} + +/// Load the realm list from the database +void RealmList::Initialize(uint32 updateInterval) +{ + m_UpdateInterval = updateInterval; + + ///- Get the content of the realmlist table in the database + UpdateRealms(true); +} + +void RealmList::UpdateRealm( uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu) +{ + ///- Create new if not exist or update existed + Realm& realm = m_realms[name]; + + realm.m_ID = ID; + realm.icon = icon; + realm.color = color; + realm.timezone = timezone; + realm.allowedSecurityLevel = allowedSecurityLevel; + realm.populationLevel = popu; + + ///- Append port to IP address. + std::ostringstream ss; + ss << address << ":" << port; + realm.address = ss.str(); +} + +void RealmList::UpdateIfNeed() +{ + // maybe disabled or updated recently + if(!m_UpdateInterval || m_NextUpdateTime > time(NULL)) + return; + + m_NextUpdateTime = time(NULL) + m_UpdateInterval; + + // Clears Realm list + m_realms.clear(); + + // Get the content of the realmlist table in the database + UpdateRealms(false); +} + +void RealmList::UpdateRealms(bool init) +{ + sLog.outDetail("Updating Realm List..."); + + QueryResult *result = LoginDatabase.Query( "SELECT id, name, address, port, icon, color, timezone, allowedSecurityLevel, population FROM realmlist WHERE color <> 3 ORDER BY name" ); + + ///- Circle through results and add them to the realm map + if(result) + { + do + { + Field *fields = result->Fetch(); + + uint8 allowedSecurityLevel = fields[7].GetUInt8(); + + UpdateRealm(fields[0].GetUInt32(), fields[1].GetCppString(),fields[2].GetCppString(),fields[3].GetUInt32(),fields[4].GetUInt8(), fields[5].GetUInt8(), fields[6].GetUInt8(), (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), fields[8].GetFloat() ); + if(init) + sLog.outString("Added realm \"%s\".", fields[1].GetString()); + } while( result->NextRow() ); + delete result; + } +} diff --git a/src/realmd/RealmList.h b/src/realmd/RealmList.h new file mode 100644 index 00000000000..b830a0827a7 --- /dev/null +++ b/src/realmd/RealmList.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/// \addtogroup realmd +/// @{ +/// \file + +#ifndef _REALMLIST_H +#define _REALMLIST_H + +#include "Common.h" + +/// Storage object for a realm +struct Realm +{ + std::string address; + uint8 icon; + uint8 color; + uint8 timezone; + uint32 m_ID; + AccountTypes allowedSecurityLevel; + float populationLevel; +}; + +/// Storage object for the list of realms on the server +class RealmList +{ + public: + typedef std::map<std::string, Realm> RealmMap; + + RealmList(); + ~RealmList() {} + + void Initialize(uint32 updateInterval); + + void UpdateIfNeed(); + + RealmMap::const_iterator begin() const { return m_realms.begin(); } + RealmMap::const_iterator end() const { return m_realms.end(); } + uint32 size() const { return m_realms.size(); } + private: + void UpdateRealms(bool init); + void UpdateRealm( uint32 ID, const std::string& name, const std::string& address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu); + private: + RealmMap m_realms; ///< Internal map of realms + uint32 m_UpdateInterval; + time_t m_NextUpdateTime; +}; +#endif +/// @} diff --git a/src/trinityrealm/TrinityRealm.ico b/src/realmd/TrinityRealm.ico Binary files differindex da318f48a8c..da318f48a8c 100644 --- a/src/trinityrealm/TrinityRealm.ico +++ b/src/realmd/TrinityRealm.ico diff --git a/src/trinityrealm/trinityrealm.conf.dist b/src/realmd/realmd.conf.dist.in index 72ef1c9012e..72ef1c9012e 100644 --- a/src/trinityrealm/trinityrealm.conf.dist +++ b/src/realmd/realmd.conf.dist.in diff --git a/src/trinityrealm/TrinityRealm.rc b/src/realmd/realmd.rc index 33c7eef719a..bcd37f240c5 100644 --- a/src/trinityrealm/TrinityRealm.rc +++ b/src/realmd/realmd.rc @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/realmd/resource.h b/src/realmd/resource.h new file mode 100644 index 00000000000..7e7d8e4b76f --- /dev/null +++ b/src/realmd/resource.h @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by TrinityCore.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/src/shared/Auth/AuthCrypt.cpp b/src/shared/Auth/AuthCrypt.cpp index d45c56817ba..2d8bd824fd1 100644 --- a/src/shared/Auth/AuthCrypt.cpp +++ b/src/shared/Auth/AuthCrypt.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -50,9 +50,8 @@ void AuthCrypt::DecryptRecv(uint8 *data, size_t len) void AuthCrypt::EncryptSend(uint8 *data, size_t len) { if (!_initialized) return; - if (len < CRYPTED_SEND_LEN) return; - for (size_t t = 0; t < CRYPTED_SEND_LEN; t++) + for (size_t t = 0; t < len; t++) { _send_i %= _key.size(); uint8 x = (data[t] ^ _key[_send_i]) + _send_j; @@ -67,7 +66,7 @@ void AuthCrypt::SetKey(BigNumber *bn) GenerateKey(key, bn); _key.resize(SHA_DIGEST_LENGTH); std::copy(key, key + SHA_DIGEST_LENGTH, _key.begin()); - delete key; + delete[] key; } AuthCrypt::~AuthCrypt() diff --git a/src/shared/Auth/AuthCrypt.h b/src/shared/Auth/AuthCrypt.h index b007e8c3d0e..7a0b0a4d219 100644 --- a/src/shared/Auth/AuthCrypt.h +++ b/src/shared/Auth/AuthCrypt.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,7 +32,6 @@ class AuthCrypt AuthCrypt(); ~AuthCrypt(); - const static size_t CRYPTED_SEND_LEN = 4; const static size_t CRYPTED_RECV_LEN = 6; void Init(); diff --git a/src/shared/Auth/BigNumber.cpp b/src/shared/Auth/BigNumber.cpp index 2baba88e9e0..becbe44c0ed 100644 --- a/src/shared/Auth/BigNumber.cpp +++ b/src/shared/Auth/BigNumber.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Auth/BigNumber.h b/src/shared/Auth/BigNumber.h index 37979bdd76f..9ce18ea3047 100644 --- a/src/shared/Auth/BigNumber.h +++ b/src/shared/Auth/BigNumber.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Auth/Hmac.cpp b/src/shared/Auth/Hmac.cpp index 91c065d3640..5f97ee65cc2 100644 --- a/src/shared/Auth/Hmac.cpp +++ b/src/shared/Auth/Hmac.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Auth/Hmac.h b/src/shared/Auth/Hmac.h index 1c19ec2238d..b8ab30f2dc7 100644 --- a/src/shared/Auth/Hmac.h +++ b/src/shared/Auth/Hmac.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Auth/Makefile.am b/src/shared/Auth/Makefile.am index 9c71613a0de..2d4cc03902d 100644 --- a/src/shared/Auth/Makefile.am +++ b/src/shared/Auth/Makefile.am @@ -1,6 +1,6 @@ -# Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> # -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -9,19 +9,19 @@ # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Process this file with automake to produce Makefile.in ## Sub-directories to parse ## CPP flags for includes, defines, etc. -AM_CPPFLAGS = $(MYSQL_INCLUDES) $(POSTGRE_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite +AM_CPPFLAGS = $(TRINI_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite ## Build MaNGOS shared library and its parts as convenience library. # All libraries will be convenience libraries. Might be changed to shared @@ -29,13 +29,13 @@ AM_CPPFLAGS = $(MYSQL_INCLUDES) $(POSTGRE_INCLUDES) -I$(top_builddir)/src/shared noinst_LIBRARIES = libmangosauth.a libmangosauth_a_SOURCES = \ - AuthCrypt.cpp \ - AuthCrypt.h \ - BigNumber.cpp \ - BigNumber.h \ - Hmac.cpp \ - Hmac.h \ - Sha1.cpp \ - Sha1.h \ - md5.c \ - md5.h + AuthCrypt.cpp \ + AuthCrypt.h \ + BigNumber.cpp \ + BigNumber.h \ + Hmac.cpp \ + Hmac.h \ + Sha1.cpp \ + Sha1.h \ + md5.c \ + md5.h diff --git a/src/shared/Auth/Sha1.cpp b/src/shared/Auth/Sha1.cpp index 73fcf90bfa8..f367c2919b3 100644 --- a/src/shared/Auth/Sha1.cpp +++ b/src/shared/Auth/Sha1.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Auth/Sha1.h b/src/shared/Auth/Sha1.h index d748dc6d747..811ccc2053a 100644 --- a/src/shared/Auth/Sha1.h +++ b/src/shared/Auth/Sha1.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/ByteBuffer.h b/src/shared/ByteBuffer.h index 3d0d19d9120..2dd01e8a022 100644 --- a/src/shared/ByteBuffer.h +++ b/src/shared/ByteBuffer.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -243,6 +243,32 @@ class ByteBuffer _rpos += len; } + bool readPackGUID(uint64& guid) + { + if(rpos()+1 > size()) + return false; + + guid = 0; + + uint8 guidmark=0; + (*this) >> guidmark; + + for(int i=0;i<8;i++) + { + if(guidmark & (uint8(1) << i)) + { + if(rpos()+1 > size()) + return false; + + uint8 bit; + (*this) >> bit; + guid |= (uint64(bit) << (i*8)); + } + } + + return true; + } + const uint8 *contents() const { return &_storage[0]; } size_t size() const { return _storage.size(); } diff --git a/src/shared/Common.cpp b/src/shared/Common.cpp index db039b93a82..e70dc8358c2 100644 --- a/src/shared/Common.cpp +++ b/src/shared/Common.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Common.h b/src/shared/Common.h index c97de30ed46..a0884a8455e 100644 --- a/src/shared/Common.h +++ b/src/shared/Common.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -80,6 +80,8 @@ #pragma warning(disable:4305) #pragma warning(disable:4005) + +#pragma warning(disable:4522)//warning when class has 2 constructosr #endif // __SHOW_STUPID_WARNINGS__ #endif // __GNUC__ diff --git a/src/shared/Config/Config.cpp b/src/shared/Config/Config.cpp index 1dacb55b670..b3a3b13d652 100644 --- a/src/shared/Config/Config.cpp +++ b/src/shared/Config/Config.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Config/Config.h b/src/shared/Config/Config.h index 7347d3ee7a1..424c369bd92 100644 --- a/src/shared/Config/Config.h +++ b/src/shared/Config/Config.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Config/ConfigEnv.h b/src/shared/Config/ConfigEnv.h index 09877cbd296..6c3a54a45fc 100644 --- a/src/shared/Config/ConfigEnv.h +++ b/src/shared/Config/ConfigEnv.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Config/Makefile.am b/src/shared/Config/Makefile.am index 23188ba3447..4854095b98c 100644 --- a/src/shared/Config/Makefile.am +++ b/src/shared/Config/Makefile.am @@ -1,6 +1,6 @@ -# Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> # -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -9,19 +9,19 @@ # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Process this file with automake to produce Makefile.in ## Sub-directories to parse ## CPP flags for includes, defines, etc. -AM_CPPFLAGS = $(MYSQL_INCLUDES) $(POSTGRE_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite +AM_CPPFLAGS = $(TRINI_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite ## Build MaNGOS shared library and its parts as convenience library. # All libraries will be convenience libraries. Might be changed to shared diff --git a/src/shared/Config/dotconfpp/dotconfpp.cpp b/src/shared/Config/dotconfpp/dotconfpp.cpp index 543e8acf1f4..c46b1fe6fb9 100644 --- a/src/shared/Config/dotconfpp/dotconfpp.cpp +++ b/src/shared/Config/dotconfpp/dotconfpp.cpp @@ -138,7 +138,7 @@ int DOTCONFDocument::cleanupLine(char * line) quoted = !quoted; ++line; continue; } - if(isspace(*line) && !quoted){ + if(isspace((unsigned char)*line) && !quoted){ *bg++ = 0; if(strlen(start)){ @@ -154,7 +154,7 @@ int DOTCONFDocument::cleanupLine(char * line) words.push_back(word); } start = bg; - while(isspace(*++line)) {} + while(isspace((unsigned char)*++line)) {} continue; } diff --git a/src/shared/Database/DBCEnums.h b/src/shared/Database/DBCEnums.h index 1d54616a2b5..e546b1f7828 100644 --- a/src/shared/Database/DBCEnums.h +++ b/src/shared/Database/DBCEnums.h @@ -1,5 +1,5 @@ /* -* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/> +* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,28 +34,190 @@ enum AreaTeams AREATEAM_HORDE = 4 }; +enum AchievementFactionFlags +{ + ACHIEVEMENT_FACTION_FLAG_HORDE = 0x00000000, + ACHIEVEMENT_FACTION_FLAG_ALLIANCE = 0x00000001, +}; + +enum AchievementFlags +{ + ACHIEVEMENT_FLAG_COUNTER = 0x00000001, + ACHIEVEMENT_FLAG_REACH_LEVEL = 0x00000004, + ACHIEVEMENT_FLAG_RERERED_MAX = 0x00000010, // displays the maximum criteria of a refered achievement + ACHIEVEMENT_FLAG_AVERAGE = 0x00000040, + ACHIEVEMENT_FLAG_REALM_FIRST_REACH= 0x00000100, + ACHIEVEMENT_FLAG_REALM_FIRST_KILL = 0x00000200, +}; + +enum AchievementCriteriaCondition +{ + ACHIEVEMENT_CRITERIA_CONDITION_NONE = 0, + ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH = 1, + ACHIEVEMENT_CRITERIA_CONDITION_UNK1 = 2, // only used in "Complete a daily quest every day for five consecutive days" + ACHIEVEMENT_CRITERIA_CONDITION_MAP = 3, // requires you to be on specific map + ACHIEVEMENT_CRITERIA_CONDITION_NO_LOOSE = 4, // only used in "Win 10 arenas without losing" + ACHIEVEMENT_CRITERIA_CONDITION_UNK2 = 9, // unk + ACHIEVEMENT_CRITERIA_CONDITION_UNK3 = 13, // unk +}; + +enum AchievementCriteriaCompletionFlags +{ + // some Achievements (like 698) have several criteria but only one has to be fulfilled. These are identified by this flag. + ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL = 2, +}; + +enum AchievementCriteriaGroupFlags +{ + // you mustn't be in a group while fulfilling this achievement + ACHIEVEMENT_CRITERIA_GROUP_NOT_IN_GROUP = 2, +}; + +enum AchievementCriteriaTypes +{ + ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0, + ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1, + ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5, + ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9, + // you have to complete a daily quest x times in a row + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11, + ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND= 15, + ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP= 16, + // TODO: this can be both arena and total deaths. Where is this difference in the dbc? + ACHIEVEMENT_CRITERIA_TYPE_DEATH= 17, + ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19, + ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20, + ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER = 23, + ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24, + ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26, + ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27, + ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28, + ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL= 29, + ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE = 30, + ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31, + ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32, + ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34, + // TODO: this criteria has additional conditions which can not be found in the dbcs + ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL = 35, + ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36, + // TODO: the archievements 1162 and 1163 requires a special rating which can't be found in the dbc + ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38, + ACHIEVEMENT_CRITERIA_TYPE_REACH_TEAM_RATING = 39, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40, + ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM= 42, + ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43, + ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK= 44, + ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT= 45, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION= 46, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION= 47, + // noted: rewarded as soon as the player payed, not at taking place at the seat + ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP= 48, + ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49, + // TODO: itemlevel is mentioned in text but not present in dbc + ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50, + ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT= 51, + ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52, + ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53, + ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54, + ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55, + // TODO: in some cases map not present, and in some cases need do without die + ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56, + ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57, + ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS = 59, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS = 60, + ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS = 61, + ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING = 63, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER = 65, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL = 66, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67, + ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68, + ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2= 69, + ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL= 70, + ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72, + // TODO: title id is not mentioned in dbc + ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE = 74, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS= 75, + ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76, + ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL = 77, + // TODO: creature type (demon, undead etc.) is not stored in dbc + ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE = 78, + ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS= 80, + ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION= 82, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID= 83, + ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS= 84, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD = 85, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED = 86, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION = 87, + ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION = 88, + ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS = 89, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM = 90, + ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91, + ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED = 93, + ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED = 94, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH = 95, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER = 96, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT = 97, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER = 98, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR = 99, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING = 100, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102, + ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED = 104, + ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED = 105, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED = 106, + ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED = 107, + ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN = 108, + ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109, + // TODO: target entry is missing + ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110, + ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE= 112, + ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113, + ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114, + // 0..114 => 115 criteria types total + ACHIEVEMENT_CRITERIA_TYPE_TOTAL = 115, +}; + enum AreaFlags { AREA_FLAG_SNOW = 0x00000001, // snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring) - AREA_FLAG_UNK1 = 0x00000002, // unknown, (only Naxxramas and Razorfen Downs) - AREA_FLAG_UNK2 = 0x00000004, // Only used on development map - AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // slave capital city flag? - AREA_FLAG_UNK3 = 0x00000010, // unknown + AREA_FLAG_UNK1 = 0x00000002, // may be necropolis? + AREA_FLAG_UNK2 = 0x00000004, // Only used for areas on map 571 (development before) + AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // city and city subsones + AREA_FLAG_UNK3 = 0x00000010, // can't find common meaning AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag? AREA_FLAG_UNK4 = 0x00000040, // many zones have this flag AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?) - AREA_FLAG_OUTLAND = 0x00000400, // outland zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag) + AREA_FLAG_OUTLAND = 0x00000400, // expansion zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag) AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled) AREA_FLAG_NEED_FLY = 0x00001000, // only Netherwing Ledge, Socrethar's Seat, Tempest Keep, The Arcatraz, The Botanica, The Mechanar, Sorrow Wing Point, Dragonspine Ridge, Netherwing Mines, Dragonmaw Base Camp, Dragonmaw Skyway - AREA_FLAG_UNUSED1 = 0x00002000, // not used now (no area/zones with this flag set in 2.4.2) - AREA_FLAG_OUTLAND2 = 0x00004000, // outland zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag) + AREA_FLAG_UNUSED1 = 0x00002000, // not used now (no area/zones with this flag set in 3.0.3) + AREA_FLAG_OUTLAND2 = 0x00004000, // expansion zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag) AREA_FLAG_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area) AREA_FLAG_ARENA_INSTANCE = 0x00010000, // used by instanced arenas only - AREA_FLAG_UNUSED2 = 0x00020000, // not used now (no area/zones with this flag set in 2.4.2) - AREA_FLAG_UNK5 = 0x00040000, // just used for Amani Pass, Hatchet Hills - AREA_FLAG_LOWLEVEL = 0x00100000 // used for some starting areas with area_level <=15 + AREA_FLAG_UNUSED2 = 0x00020000, // not used now (no area/zones with this flag set in 3.0.3) + AREA_FLAG_UNK5 = 0x00040000, // only used for Amani Pass, Hatchet Hills + AREA_FLAG_UNK6 = 0x00080000, // Valgarde and Acherus: The Ebon Hold + AREA_FLAG_LOWLEVEL = 0x00100000, // used for some starting areas with area_level <=15 + AREA_FLAG_TOWN = 0x00200000, // small towns with Inn + AREA_FLAG_UNK7 = 0x00400000, // Warsong Hold, Acherus: The Ebon Hold, New Agamand Inn, Vengeance Landing Inn + AREA_FLAG_UNK8 = 0x00800000, // Westguard Inn, Acherus: The Ebon Hold, Valgarde + AREA_FLAG_OUTDOOR_PVP = 0x01000000, // Wintergrasp and it's subzones + AREA_FLAG_UNK9 = 0x02000000, // unknown + AREA_FLAG_UNK10 = 0x04000000, // unknown + AREA_FLAG_OUTDOOR_PVP2 = 0x08000000 // Wintergrasp and it's subzones }; enum FactionTemplateFlags @@ -89,13 +251,15 @@ enum AbilytyLearnType enum ItemEnchantmentType { - ITEM_ENCHANTMENT_TYPE_NONE = 0, - ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL = 1, - ITEM_ENCHANTMENT_TYPE_DAMAGE = 2, - ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL = 3, - ITEM_ENCHANTMENT_TYPE_RESISTANCE = 4, - ITEM_ENCHANTMENT_TYPE_STAT = 5, - ITEM_ENCHANTMENT_TYPE_TOTEM = 6 + ITEM_ENCHANTMENT_TYPE_NONE = 0, + ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL = 1, + ITEM_ENCHANTMENT_TYPE_DAMAGE = 2, + ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL = 3, + ITEM_ENCHANTMENT_TYPE_RESISTANCE = 4, + ITEM_ENCHANTMENT_TYPE_STAT = 5, + ITEM_ENCHANTMENT_TYPE_TOTEM = 6, + ITEM_ENCHANTMENT_TYPE_USE_SPELL = 7, + ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET = 8 }; enum TotemCategoryType @@ -109,4 +273,51 @@ enum TotemCategoryType TOTEM_CATEGORY_TYPE_SPANNER = 24 }; +// SummonProperties.dbc, col 1 +/*enum SummonGroup +{ + SUMMON_GROUP_UNKNOWN1 = 0, // 1160 spells in 3.0.3 + SUMMON_GROUP_UNKNOWN2 = 1, // 861 spells in 3.0.3 + SUMMON_GROUP_PETS = 2, // 52 spells in 3.0.3, pets mostly + SUMMON_GROUP_CONTROLLABLE = 3, // 13 spells in 3.0.3, mostly controllable + SUMMON_GROUP_UNKNOWN3 = 4 // 86 spells in 3.0.3, taxi/mounts +}; + +// SummonProperties.dbc, col 3 +enum SummonType +{ + SUMMON_TYPE_UNKNOWN = 0, // different summons, 1330 spells in 3.0.3 + SUMMON_TYPE_SUMMON = 1, // generic summons, 49 spells in 3.0.3 + SUMMON_TYPE_GUARDIAN = 2, // summon guardian, 393 spells in 3.0.3 + SUMMON_TYPE_ARMY = 3, // summon army, 5 spells in 3.0.3 + SUMMON_TYPE_TOTEM = 4, // summon totem, 169 spells in 3.0.3 + SUMMON_TYPE_CRITTER = 5, // critter/minipet, 195 spells in 3.0.3 + SUMMON_TYPE_DK = 6, // summon DRW/Ghoul, 2 spells in 3.0.3 + SUMMON_TYPE_BOMB = 7, // summon bot/bomb, 4 spells in 3.0.3 + SUMMON_TYPE_PHASING = 8, // something todo with DK prequest line, 2 spells in 3.0.3 + SUMMON_TYPE_SIEGE_VEH = 9, // summon different vehicles, 14 spells in 3.0.3 + SUMMON_TYPE_DRAKE_VEH = 10, // summon drake (vehicle), 3 spells + SUMMON_TYPE_LIGHTWELL = 11 // summon lightwell, 6 spells in 3.0.3 +}; + +// SummonProperties.dbc, col 5 +enum SummonFlags +{ + SUMMON_FLAG_NONE = 0x0000, // 1342 spells in 3.0.3 + SUMMON_FLAG_UNK1 = 0x0001, // 75 spells in 3.0.3, something unfriendly + SUMMON_FLAG_UNK2 = 0x0002, // 616 spells in 3.0.3, something friendly + SUMMON_FLAG_UNK3 = 0x0004, // 22 spells in 3.0.3, no idea... + SUMMON_FLAG_UNK4 = 0x0008, // 49 spells in 3.0.3, some mounts + SUMMON_FLAG_UNK5 = 0x0010, // 25 spells in 3.0.3, quest related? + SUMMON_FLAG_UNK6 = 0x0020, // 0 spells in 3.0.3, unused + SUMMON_FLAG_UNK7 = 0x0040, // 12 spells in 3.0.3, no idea + SUMMON_FLAG_UNK8 = 0x0080, // 4 spells in 3.0.3, no idea + SUMMON_FLAG_UNK9 = 0x0100, // 51 spells in 3.0.3, no idea, many quest related + SUMMON_FLAG_UNK10 = 0x0200, // 51 spells in 3.0.3, something defensive + SUMMON_FLAG_UNK11 = 0x0400, // 3 spells, requires something near? + SUMMON_FLAG_UNK12 = 0x0800, // 30 spells in 3.0.3, no idea + SUMMON_FLAG_UNK13 = 0x1000, // 8 spells in 3.0.3, siege vehicle + SUMMON_FLAG_UNK14 = 0x2000, // 2 spells in 3.0.3, escort? +}; +*/ #endif diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp index fb132c75768..9a5605060fb 100644 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,12 +32,16 @@ typedef std::map<uint16,uint32> AreaFlagByAreaID; typedef std::map<uint32,uint32> AreaFlagByMapID; DBCStorage <AreaTableEntry> sAreaStore(AreaTableEntryfmt); +DBCStorage <AreaGroupEntry> sAreaGroupStore(AreaGroupEntryfmt); static AreaFlagByAreaID sAreaFlagByAreaID; static AreaFlagByMapID sAreaFlagByMapID; // for instances without generated *.map files +DBCStorage <AchievementEntry> sAchievementStore(Achievementfmt); +DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore(AchievementCriteriafmt); DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt); DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt); DBCStorage <BattlemasterListEntry> sBattlemasterListStore(BattlemasterListEntryfmt); +DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore(BarberShopStyleEntryfmt); DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore(CharStartOutfitEntryfmt); DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt); DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt); @@ -46,6 +50,7 @@ DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt); DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt); DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore(CreatureFamilyfmt); DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore(CreatureSpellDatafmt); +DBCStorage <CreatureTypeEntry> sCreatureTypeStore(CreatureTypefmt); DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore(DurabilityQualityfmt); DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCostsfmt); @@ -58,7 +63,10 @@ DBCStorage <FactionEntry> sFactionStore(FactionEntryfmt); DBCStorage <FactionTemplateEntry> sFactionTemplateStore(FactionTemplateEntryfmt); DBCStorage <GemPropertiesEntry> sGemPropertiesStore(GemPropertiesEntryfmt); +DBCStorage <GlyphPropertiesEntry> sGlyphPropertiesStore(GlyphPropertiesfmt); +DBCStorage <GlyphSlotEntry> sGlyphSlotStore(GlyphSlotfmt); +DBCStorage <GtBarberShopCostBaseEntry> sGtBarberShopCostBaseStore(GtBarberShopCostBasefmt); DBCStorage <GtCombatRatingsEntry> sGtCombatRatingsStore(GtCombatRatingsfmt); DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore(GtChanceToMeleeCritBasefmt); DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore(GtChanceToMeleeCritfmt); @@ -84,6 +92,8 @@ DBCStorage <MapEntry> sMapStore(MapEntryfmt); DBCStorage <QuestSortEntry> sQuestSortStore(QuestSortEntryfmt); DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore(RandomPropertiesPointsfmt); +DBCStorage <ScalingStatDistributionEntry> sScalingStatDistributionStore(ScalingStatDistributionfmt); +DBCStorage <ScalingStatValuesEntry> sScalingStatValuesStore(ScalingStatValuesfmt); DBCStorage <SkillLineEntry> sSkillLineStore(SkillLinefmt); DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore(SkillLineAbilityfmt); @@ -101,8 +111,10 @@ DBCStorage <SpellDurationEntry> sSpellDurationStore(SpellDurationfmt); DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore(SpellFocusObjectfmt); DBCStorage <SpellRadiusEntry> sSpellRadiusStore(SpellRadiusfmt); DBCStorage <SpellRangeEntry> sSpellRangeStore(SpellRangefmt); +DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore(SpellRuneCostfmt); DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore(SpellShapeshiftfmt); DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore(StableSlotPricesfmt); +//DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore(SummonPropertiesfmt); DBCStorage <TalentEntry> sTalentStore(TalentEntryfmt); TalentSpellPosMap sTalentSpellPosMap; DBCStorage <TalentTabEntry> sTalentTabStore(TalentTabEntryfmt); @@ -125,8 +137,11 @@ TaxiPathNodesByPath sTaxiPathNodesByPath; static DBCStorage <TaxiPathNodeEntry> sTaxiPathNodeStore(TaxiPathNodeEntryfmt); DBCStorage <TotemCategoryEntry> sTotemCategoryStore(TotemCategoryEntryfmt); +DBCStorage <VehicleEntry> sVehicleStore(VehicleEntryfmt); +DBCStorage <VehicleSeatEntry> sVehicleSeatStore(VehicleSeatEntryfmt); DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt); DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt); +DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore(WorldMapOverlayEntryfmt); typedef std::list<std::string> StoreProblemList; @@ -178,7 +193,7 @@ void LoadDBCStores(const std::string& dataPath) { std::string dbcPath = dataPath+"dbc/"; - const uint32 DBCFilesCount = 56; + const uint32 DBCFilesCount = 70; barGoLink bar( DBCFilesCount ); @@ -196,14 +211,18 @@ void LoadDBCStores(const std::string& dataPath) sAreaFlagByAreaID.insert(AreaFlagByAreaID::value_type(uint16(area->ID),area->exploreFlag)); // fill MapId->DBC records ( skip sub zones and continents ) - if(area->zone==0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 ) + if(area->zone==0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 && area->mapid != 571 ) sAreaFlagByMapID.insert(AreaFlagByMapID::value_type(area->mapid,area->exploreFlag)); } } + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAchievementStore, dbcPath,"Achievement.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAchievementCriteriaStore, dbcPath,"Achievement_Criteria.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaTriggerStore, dbcPath,"AreaTrigger.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaGroupStore, dbcPath,"AreaGroup.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBankBagSlotPricesStore, dbcPath,"BankBagSlotPrices.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBattlemasterListStore, dbcPath,"BattlemasterList.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBarberShopStyleStore, dbcPath,"BarberShopStyle.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharStartOutfitStore, dbcPath,"CharStartOutfit.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharTitlesStore, dbcPath,"CharTitles.dbc"); @@ -213,6 +232,7 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureDisplayInfoStore, dbcPath,"CreatureDisplayInfo.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureFamilyStore, dbcPath,"CreatureFamily.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureSpellDataStore, dbcPath,"CreatureSpellData.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureTypeStore, dbcPath,"CreatureType.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityQualityStore, dbcPath,"DurabilityQuality.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesTextStore, dbcPath,"EmotesText.dbc"); @@ -229,7 +249,10 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionTemplateStore, dbcPath,"FactionTemplate.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGemPropertiesStore, dbcPath,"GemProperties.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphPropertiesStore, dbcPath,"GlyphProperties.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGlyphSlotStore, dbcPath,"GlyphSlot.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtBarberShopCostBaseStore,dbcPath,"gtBarberShopCostBase.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtCombatRatingsStore, dbcPath,"gtCombatRatings.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritBaseStore, dbcPath,"gtChanceToMeleeCritBase.dbc"); @@ -254,6 +277,8 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapStore, dbcPath,"Map.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestSortStore, dbcPath,"QuestSort.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sRandomPropertiesPointsStore, dbcPath,"RandPropPoints.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatDistributionStore, dbcPath,"ScalingStatDistribution.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sScalingStatValuesStore, dbcPath,"ScalingStatValues.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc"); @@ -264,11 +289,11 @@ void LoadDBCStores(const std::string& dataPath) if(spell && spell->Category) sSpellCategoryStore[spell->Category].insert(i); - // DBC not support uint64 fields but SpellEntry have SpellFamilyFlags mapped at 2 uint32 fields + /*// DBC not support uint64 fields but SpellEntry have SpellFamilyFlags mapped at 2 uint32 fields // uint32 field already converted to bigendian if need, but must be swapped for correct uint64 bigendian view #if TRINITY_ENDIAN == TRINITY_BIGENDIAN std::swap(*((uint32*)(&spell->SpellFamilyFlags)),*(((uint32*)(&spell->SpellFamilyFlags))+1)); - #endif + #endif*/ } for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j) @@ -303,8 +328,10 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentConditionStore,dbcPath,"SpellItemEnchantmentCondition.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRadiusStore, dbcPath,"SpellRadius.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRangeStore, dbcPath,"SpellRange.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRuneCostStore, dbcPath,"SpellRuneCost.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellShapeshiftStore, dbcPath,"SpellShapeshiftForm.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sStableSlotPricesStore, dbcPath,"StableSlotPrices.dbc"); + //LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSummonPropertiesStore, dbcPath,"SummonProperties.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentStore, dbcPath,"Talent.dbc"); // create talent spells set @@ -382,18 +409,6 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiNodesStore, dbcPath,"TaxiNodes.dbc"); - // Initialize global taxinodes mask - memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask)); - for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) - { - if(sTaxiNodesStore.LookupEntry(i)) - { - uint8 field = (uint8)((i - 1) / 32); - uint32 submask = 1<<((i-1)%32); - sTaxiNodesMask[field] |= submask; - } - } - LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathStore, dbcPath,"TaxiPath.dbc"); for(uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i) if(TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i)) @@ -407,7 +422,10 @@ void LoadDBCStores(const std::string& dataPath) pathLength.resize(pathCount); // 0 and some other indexes not used for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i) if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i)) - ++pathLength[entry->path]; + { + if (pathLength[entry->path] < entry->index + 1) + pathLength[entry->path] = entry->index + 1; + } // Set path length sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used for(uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i) @@ -418,9 +436,53 @@ void LoadDBCStores(const std::string& dataPath) sTaxiPathNodesByPath[entry->path][entry->index] = TaxiPathNode(entry->mapid,entry->x,entry->y,entry->z,entry->actionFlag,entry->delay); sTaxiPathNodeStore.Clear(); + // Initialize global taxinodes mask + // include existed nodes that have at least single not spell base (scripted) path + { + std::set<uint32> spellPaths; + for(uint32 i = 1; i < sSpellStore.GetNumRows (); ++i) + if(SpellEntry const* sInfo = sSpellStore.LookupEntry (i)) + for(int j=0; j < 3; ++j) + if(sInfo->Effect[j]==123 /*SPELL_EFFECT_SEND_TAXI*/) + spellPaths.insert(sInfo->EffectMiscValue[j]); + + memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask)); + for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i) + { + if(!sTaxiNodesStore.LookupEntry(i)) + continue; + + TaxiPathSetBySource::const_iterator src_i = sTaxiPathSetBySource.find(i); + if(src_i!=sTaxiPathSetBySource.end() && !src_i->second.empty()) + { + bool ok = false; + for(TaxiPathSetForSource::const_iterator dest_i = src_i->second.begin();dest_i != src_i->second.end(); ++dest_i) + { + // not spell path + if(spellPaths.find(dest_i->second.ID)==spellPaths.end()) + { + ok = true; + break; + } + } + + if(!ok) + continue; + } + + // valid taxi netowrk node + uint8 field = (uint8)((i - 1) / 32); + uint32 submask = 1<<((i-1)%32); + sTaxiNodesMask[field] |= submask; + } + } + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTotemCategoryStore, dbcPath,"TotemCategory.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleStore, dbcPath,"Vehicle.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sVehicleSeatStore, dbcPath,"VehicleSeat.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapAreaStore, dbcPath,"WorldMapArea.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldSafeLocsStore, dbcPath,"WorldSafeLocs.dbc"); + LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapOverlayStore, dbcPath,"WorldMapOverlay.dbc"); // error checks if(bad_dbc_files.size() >= DBCFilesCount ) @@ -438,28 +500,22 @@ void LoadDBCStores(const std::string& dataPath) exit(1); } - // check at up-to-date DBC files (53085 is last added spell in 2.4.3) - // check at up-to-date DBC files (17514 is last ID in SkillLineAbilities in 2.4.3) - // check at up-to-date DBC files (598 is last map added in 2.4.3) - // check at up-to-date DBC files (1127 is last gem property added in 2.4.3) - // check at up-to-date DBC files (2425 is last item extended cost added in 2.4.3) - // check at up-to-date DBC files (71 is last char title added in 2.4.3) - // check at up-to-date DBC files (1768 is last area added in 2.4.3) - if( !sSpellStore.LookupEntry(53085) || - !sSkillLineAbilityStore.LookupEntry(17514) || - !sMapStore.LookupEntry(598) || - !sGemPropertiesStore.LookupEntry(1127) || - !sItemExtendedCostStore.LookupEntry(2425) || - !sCharTitlesStore.LookupEntry(71) || - !sAreaStore.LookupEntry(1768) ) + // Check loaded DBC files proper version + if( !sSpellStore.LookupEntry(54909) || // last added spell in 3.0.8a + !sSpellStore.LookupEntry(49184) || // last added spell in 3.0.8a + sSpellStore.LookupEntry(49184)->RecoveryTime!=5000||// last changed spell in 3.0.8a + !sMapStore.LookupEntry(624) || // last map added in 3.0.8a + !sGemPropertiesStore.LookupEntry(1557) || // last gem property added in 3.0.8a + !sItemExtendedCostStore.LookupEntry(2589) || // last item extended cost added in 3.0.8a + !sCharTitlesStore.LookupEntry(144) || // last char title added in 3.0.8a + !sAreaStore.LookupEntry(2769) ) // last area (areaflag) added in 3.0.8a { sLog.outError("\nYou have _outdated_ DBC files. Please extract correct versions from current using client."); exit(1); } sLog.outString(); - sLog.outString( ">> Loaded %d data stores", DBCFilesCount ); - sLog.outString(); + sLog.outString( ">> Initialized %d data stores", DBCFilesCount ); } SimpleFactionsList const* GetFactionTeamList(uint32 faction) @@ -537,7 +593,7 @@ uint32 GetAreaFlagByMapId(uint32 mapid) uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId) { - if(mapid != 530) // speed for most cases + if(mapid != 530 && mapid != 571) // speed for most cases return mapid; if(WorldMapAreaEntry const* wma = sWorldMapAreaStore.LookupEntry(zoneId)) diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h index 98a54fbeccf..dbe5e9d3bf4 100644 --- a/src/shared/Database/DBCStores.h +++ b/src/shared/Database/DBCStores.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -132,9 +132,13 @@ class DBCStorage StringPoolList m_stringPoolList; }; +extern DBCStorage <AchievementEntry> sAchievementStore; +extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore; extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions +extern DBCStorage <AreaGroupEntry> sAreaGroupStore; extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore; extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore; +extern DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore; extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore; //extern DBCStorage <ChatChannelsEntry> sChatChannelsStore; -- accessed using function, no usable index extern DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore; @@ -144,13 +148,17 @@ extern DBCStorage <ChrRacesEntry> sChrRacesStore; extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore; extern DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore; extern DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore; +extern DBCStorage <CreatureTypeEntry> sCreatureTypeStore; extern DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore; extern DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore; extern DBCStorage <EmotesTextEntry> sEmotesTextStore; extern DBCStorage <FactionEntry> sFactionStore; extern DBCStorage <FactionTemplateEntry> sFactionTemplateStore; extern DBCStorage <GemPropertiesEntry> sGemPropertiesStore; +extern DBCStorage <GlyphPropertiesEntry> sGlyphPropertiesStore; +extern DBCStorage <GlyphSlotEntry> sGlyphSlotStore; +extern DBCStorage <GtBarberShopCostBaseEntry> sGtBarberShopCostBaseStore; extern DBCStorage <GtCombatRatingsEntry> sGtCombatRatingsStore; extern DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore; extern DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore; @@ -171,6 +179,8 @@ extern DBCStorage <MailTemplateEntry> sMailTemplateStore; extern DBCStorage <MapEntry> sMapStore; extern DBCStorage <QuestSortEntry> sQuestSortStore; extern DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore; +extern DBCStorage <ScalingStatDistributionEntry> sScalingStatDistributionStore; +extern DBCStorage <ScalingStatValuesEntry> sScalingStatValuesStore; extern DBCStorage <SkillLineEntry> sSkillLineStore; extern DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore; extern DBCStorage <SoundEntriesEntry> sSoundEntriesStore; @@ -183,9 +193,11 @@ extern SpellCategoryStore sSpellCategoryStore; extern PetFamilySpellsStore sPetFamilySpellsStore; extern DBCStorage <SpellRadiusEntry> sSpellRadiusStore; extern DBCStorage <SpellRangeEntry> sSpellRangeStore; +extern DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore; extern DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore; extern DBCStorage <SpellEntry> sSpellStore; extern DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore; +//extern DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore; extern DBCStorage <TalentEntry> sTalentStore; extern DBCStorage <TalentTabEntry> sTalentTabStore; extern DBCStorage <TaxiNodesEntry> sTaxiNodesStore; @@ -194,8 +206,11 @@ extern TaxiMask sTaxiNodesMask; extern TaxiPathSetBySource sTaxiPathSetBySource; extern TaxiPathNodesByPath sTaxiPathNodesByPath; extern DBCStorage <TotemCategoryEntry> sTotemCategoryStore; +extern DBCStorage <VehicleEntry> sVehicleStore; +extern DBCStorage <VehicleSeatEntry> sVehicleSeatStore; //extern DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates extern DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore; +extern DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore; void LoadDBCStores(const std::string& dataPath); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index f2dc8222a72..d041f8fa3b2 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ #include "DBCEnums.h" #include "Platform/Define.h" +#include "Util.h" #include <map> #include <set> @@ -37,57 +38,519 @@ #pragma pack(push,1) #endif -struct AreaTableEntry +struct AchievementEntry +{ + uint32 ID; // 0 + uint32 factionFlag; // 1 -1=all, 0=horde, 1=alliance + uint32 mapID; // 2 -1=none + //uint32 parentAchievement; // 3 its Achievement parent (can`t start while parent uncomplete, use its Criteria if don`t have own, use its progress on begin) + //char *name[16]; // 4-19 + //uint32 name_flags; // 20 + //char *description[16]; // 21-36 + //uint32 desc_flags; // 37 + uint32 categoryId; // 38 + uint32 points; // 39 reward points + //uint32 OrderInCategory; // 40 + uint32 flags; // 41 + //uint32 icon; // 42 icon (from SpellIcon.dbc) + //char *titleReward[16]; // 43-58 + //uint32 titleReward_flags; // 59 + //uint32 count; // 60 - need this count Criteria for complete + uint32 refAchievement; // 61 - related achievement? +}; + +struct AchievementCategoryEntry { uint32 ID; // 0 - uint32 mapid; // 1 - uint32 zone; // 2 if 0 then it's zone, else it's zone id of this area - uint32 exploreFlag; // 3, main index - uint32 flags; // 4, unknown value but 312 for all cities + uint32 parentCategory; // 1 -1 for main category + //char *name[16]; // 2-17 + //uint32 name_flags; // 18 + //uint32 sortOrder; // 19 +}; + +struct AchievementCriteriaEntry +{ + uint32 ID; // 0 + uint32 referredAchievement; // 1 + uint32 requiredType; // 2 + union + { + // ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0 + // TODO: also used for player deaths.. + struct + { + uint32 creatureID; // 3 + uint32 creatureCount; // 4 + } kill_creature; + + // ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1 + // TODO: there are further criterias instead just winning + struct + { + uint32 bgMapID; // 3 + uint32 winCount; // 4 + } win_bg; + + // ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5 + struct + { + uint32 unused; // 3 + uint32 level; // 4 + } reach_level; + + // ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7 + struct + { + uint32 skillID; // 3 + uint32 skillLevel; // 4 + } reach_skill_level; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8 + struct + { + uint32 linkedAchievement; // 3 + } complete_achievement; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9 + struct + { + uint32 unused; // 3 + uint32 totalQuestCount; // 4 + } complete_quest_count; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10 + struct + { + uint32 unused; // 3 + uint32 numberOfDays; // 4 + } complete_daily_quest_daily; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11 + struct + { + uint32 zoneID; // 3 + uint32 questCount; // 4 + } complete_quests_in_zone; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14 + struct + { + uint32 unused; // 3 + uint32 questCount; // 4 + } complete_daily_quest; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND= 15 + struct + { + uint32 mapID; // 3 + } complete_battleground; + + // ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP= 16 + struct + { + uint32 mapID; // 3 + } death_at_map; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19 + struct + { + uint32 groupSize; // 3 can be 5, 10 or 25 + } complete_raid; + + // ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20 + struct + { + uint32 creatureEntry; // 3 + } killed_by_creature; + + // ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24 + struct + { + uint32 unused; // 3 + uint32 fallHeight; // 4 + } fall_without_dying; + + // ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26 + struct + { + uint32 type; // 0 - fatigue, 1 - drowning, 2 - falling, 3 - ??, 5 - fire and lava + } deaths; + + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27 + struct + { + uint32 questID; // 3 + uint32 questCount; // 4 + } complete_quest; + + // ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28 + // ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2= 69 + struct + { + uint32 spellID; // 3 + uint32 spellCount; // 4 + } be_spell_target; + + // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL= 29 + // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110 + struct + { + uint32 spellID; // 3 + uint32 castCount; // 4 + } cast_spell; + + // ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31 + struct + { + uint32 areaID; // 3 Reference to AreaTable.dbc + uint32 killCount; // 4 + } honorable_kill_at_area; + + // ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32 + struct + { + uint32 mapID; // 3 Reference to Map.dbc + } win_arena; + + // ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33 + struct + { + uint32 mapID; // 3 Reference to Map.dbc + } play_arena; + + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34 + struct + { + uint32 spellID; // 3 Reference to Map.dbc + } learn_spell; + + // ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36 + struct + { + uint32 itemID; // 3 + uint32 itemCount; // 4 + } own_item; + + // ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37 + struct + { + uint32 unused; // 3 + uint32 count; // 4 + uint32 flag; // 5 4=in a row + } win_rated_arena; + + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38 + struct + { + uint32 teamtype; // 3 {2,3,5} + } highest_team_rating; + + // ACHIEVEMENT_CRITERIA_TYPE_REACH_TEAM_RATING = 39 + struct + { + uint32 teamtype; // 3 {2,3,5} + uint32 teamrating; // 4 + } reach_team_rating; + + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40 + struct + { + uint32 skillID; // 3 + uint32 skillLevel; // 4 apprentice=1, journeyman=2, expert=3, artisan=4, master=5, grand master=6 + } learn_skill_level; + + // ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41 + struct + { + uint32 itemID; // 3 + uint32 itemCount; // 4 + } use_item; + + // ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42 + struct + { + uint32 itemID; // 3 + uint32 itemCount; // 4 + } loot_item; + + // ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43 + struct + { + // TODO: This rank is _NOT_ the index from AreaTable.dbc + uint32 areaReference; // 3 + } explore_area; + + // ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK= 44 + struct + { + // TODO: This rank is _NOT_ the index from CharTitles.dbc + uint32 rank; // 3 + } own_rank; + + // ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT= 45 + struct + { + uint32 unused; // 3 + uint32 numberOfSlots; // 4 + } buy_bank_slot; + + // ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION= 46 + struct + { + uint32 factionID; // 3 + uint32 reputationAmount; // 4 Total reputation amount, so 42000 = exalted + } gain_reputation; + + // ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION= 47 + struct + { + uint32 unused; // 3 + uint32 numberOfExaltedFactions; // 4 + } gain_exalted_reputation; + + // ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP = 48 + struct + { + uint32 unused; // 3 + uint32 numberOfVisits; // 4 + } visit_barber; + + // ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49 + // TODO: where is the required itemlevel stored? + struct + { + uint32 itemSlot; // 3 + } equip_epic_item; + + // ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT= 50 + struct + { + uint32 rollValue; // 3 + uint32 count; // 4 + } roll_need_on_loot; + // ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT= 51 + struct + { + uint32 rollValue; // 3 + uint32 count; // 4 + } roll_greed_on_loot; + + // ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52 + struct + { + uint32 classID; // 3 + uint32 count; // 4 + } hk_class; + + // ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53 + struct + { + uint32 raceID; // 3 + uint32 count; // 4 + } hk_race; + + // ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54 + // TODO: where is the information about the target stored? + struct + { + uint32 emoteID; // 3 + } do_emote; + // ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13 + // ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55 + // ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56 + struct + { + uint32 unused; // 3 + uint32 count; // 4 + uint32 flag; // 5 =3 for battleground healing + uint32 mapid; // 6 + } healing_done; + + // ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57 + struct + { + uint32 itemID; // 3 + } equip_item; + + + // ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67 + struct + { + uint32 unused; // 3 + uint32 goldInCopper; // 4 + } loot_money; + + // ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68 + struct + { + uint32 goEntry; // 3 + uint32 useCount; // 4 + } use_gameobject; + + // ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL= 70 + // TODO: are those special criteria stored in the dbc or do we have to add another sql table? + struct + { + uint32 unused; // 3 + uint32 killCount; // 4 + } special_pvp_kill; + + // ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72 + struct + { + uint32 goEntry; // 3 + uint32 lootCount; // 4 + } fish_in_gameobject; + + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS= 75 + struct + { + uint32 skillLine; // 3 + uint32 spellCount; // 4 + } learn_skilline_spell; + + // ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76 + struct + { + uint32 unused; // 3 + uint32 duelCount; // 4 + } win_duel; + + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER = 96 + struct + { + uint32 powerType; // 3 mana=0, 1=rage, 3=energy, 6=runic power + } highest_power; + + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT = 97 + struct + { + uint32 statType; // 3 4=spirit, 3=int, 2=stamina, 1=agi, 0=strength + } highest_stat; + + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER = 98 + struct + { + uint32 spellSchool; // 3 + } highest_spellpower; + + // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING = 100 + struct + { + uint32 ratingType; // 3 + } highest_rating; + + // ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109 + struct + { + uint32 lootType; // 3 3=fishing, 2=pickpocket, 4=disentchant + uint32 lootTypeCount; // 4 + } loot_type; + + // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE= 112 + struct + { + uint32 skillLine; // 3 + uint32 spellCount; // 4 + } learn_skill_line; + + // ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113 + struct + { + uint32 unused; // 3 + uint32 killCount; // 4 + } honorable_kill; + + struct + { + uint32 field3; // 3 main requirement + uint32 field4; // 4 main requirement count + uint32 additionalRequirement1_type; // 5 additional requirement 1 type + uint32 additionalRequirement1_value; // 6 additional requirement 1 value + uint32 additionalRequirement2_type; // 7 additional requirement 2 type + uint32 additionalRequirement2_value; // 8 additional requirement 1 value + } raw; + }; + //char* name[16]; // 9-24 + //uint32 name_flags; // 25 + uint32 completionFlag; // 26 + uint32 groupFlag; // 27 + //uint32 unk1; // 28 + uint32 timeLimit; // 29 time limit in seconds + //uint32 showOrder; // 30 show order +}; + +struct AreaTableEntry +{ + uint32 ID; // 0 + uint32 mapid; // 1 + uint32 zone; // 2 if 0 then it's zone, else it's zone id of this area + uint32 exploreFlag; // 3, main index + uint32 flags; // 4, unknown value but 312 for all cities // 5-9 unused - int32 area_level; // 10 - char* area_name[16]; // 11-26 + int32 area_level; // 10 + char* area_name[16]; // 11-26 // 27, string flags, unused - uint32 team; // 28 + uint32 team; // 28 +}; + +struct AreaGroupEntry +{ + uint32 AreaGroupId; // 0 + uint32 AreaId[7]; // 1-7 }; struct AreaTriggerEntry { - uint32 id; // 0 - uint32 mapid; // 1 - float x; // 2 - float y; // 3 - float z; // 4 - float radius; // 5 - float box_x; // 6 extent x edge - float box_y; // 7 extent y edge - float box_z; // 8 extent z edge - float box_orientation; // 9 extent rotation by about z axis + uint32 id; // 0 m_ID + uint32 mapid; // 1 m_ContinentID + float x; // 2 m_x + float y; // 3 m_y + float z; // 4 m_z + float radius; // 5 m_radius + float box_x; // 6 m_box_length + float box_y; // 7 m_box_width + float box_z; // 8 m_box_heigh + float box_orientation; // 9 m_box_yaw }; struct BankBagSlotPricesEntry { - uint32 ID; - uint32 price; + uint32 ID; + uint32 price; +}; + +struct BarberShopStyleEntry +{ + uint32 Id; // 0 + uint32 type; // 1 value 0 -> hair, value 2 -> facialhair + //char* name[16]; // 2-17 name of hair style + //uint32 name_flags; // 18 + //uint32 unk_name[16]; // 19-34, all empty + //uint32 unk_flags; // 35 + //float CostMultiplier; // 36 values 1 and 0.75 + uint32 race; // 37 race + uint32 gender; // 38 0 -> male, 1 -> female + uint32 hair_id; // 39 real ID to hair/facial hair }; struct BattlemasterListEntry { - uint32 id; // 0 - uint32 mapid[3]; // 1-3 mapid - // 4-8 unused - uint32 type; // 9 (3 - BG, 4 - arena) - uint32 minlvl; // 10 - uint32 maxlvl; // 11 - uint32 maxplayersperteam; // 12 - // 13-14 unused - char* name[16]; // 15-30 - // 31 string flag, unused - // 32 unused + uint32 id; // 0 + int32 mapid[8]; // 1-8 mapid + uint32 type; // 9 (3 - BG, 4 - arena) + uint32 minlvl; // 10 + uint32 maxlvl; // 11 + uint32 maxplayersperteam; // 12 + // 13 minplayers + // 14 0 or 9 + // 15 + char* name[16]; // 16-31 + // 32 string flag, unused + // 33 unused }; -#define MAX_OUTFIT_ITEMS 12 -// #define MAX_OUTFIT_ITEMS 24 // 12->24 in 3.0.x +#define MAX_OUTFIT_ITEMS 24 struct CharStartOutfitEntry { @@ -103,20 +566,20 @@ struct CharStartOutfitEntry struct CharTitlesEntry { - uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId() + uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId() //uint32 unk1; // 1 flags? //char* name[16]; // 2-17, unused // 18 string flag, unused //char* name2[16]; // 19-34, unused // 35 string flag, unused - uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1<<index in PLAYER__FIELD_KNOWN_TITLES + uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1<<index in PLAYER__FIELD_KNOWN_TITLES }; struct ChatChannelsEntry { - uint32 ChannelID; // 0 - uint32 flags; // 1 - char* pattern[16]; // 3-18 + uint32 ChannelID; // 0 + uint32 flags; // 1 + char* pattern[16]; // 3-18 // 19 string flags, unused //char* name[16]; // 20-35 unused // 36 string flag, unused @@ -124,20 +587,21 @@ struct ChatChannelsEntry struct ChrClassesEntry { - uint32 ClassID; // 0 - // 1-2, unused - uint32 powerType; // 3 - // 4, unused + uint32 ClassID; // 0 + // 1, unused + uint32 powerType; // 2 + // 3-4, unused //char* name[16]; // 5-20 unused - char* name[16]; // 5-20 unused // 21 string flag, unused //char* nameFemale[16]; // 21-36 unused, if different from base (male) case // 37 string flag, unused //char* nameNeutralGender[16]; // 38-53 unused, if different from base (male) case // 54 string flag, unused // 55, unused - uint32 spellfamily; // 56 + uint32 spellfamily; // 56 // 57, unused + uint32 CinematicSequence; // 58 id from CinematicSequences.dbc + uint32 addon; // 59 (0 - original race, 1 - tbc addon, ...) }; struct ChrRacesEntry @@ -151,7 +615,7 @@ struct ChrRacesEntry // 6-7 unused uint32 TeamID; // 8 (7-Alliance 1-Horde) // 9-12 unused - uint32 startmovie; // 13 id from CinematicCamera.dbc + uint32 CinematicSequence; // 13 id from CinematicSequences.dbc char* name[16]; // 14-29 used for DBC language detection/selection // 30 string flags, unused //char* nameFemale[16]; // 31-46, if different from base (male) case @@ -164,30 +628,51 @@ struct ChrRacesEntry struct CreatureDisplayInfoEntry { - uint32 Displayid; // 0 - // 1-3,unused - float scale; // 4 - // 5-13,unused + uint32 Displayid; // 0 m_ID + // 1 m_modelID + // 2 m_soundID + // 3 m_extendedDisplayInfoID + float scale; // 4 m_creatureModelScale + // 5 m_creatureModelAlpha + // 6-8 m_textureVariation[3] + // 9 m_portraitTextureName + // 10 m_sizeClass + // 11 m_bloodID + // 12 m_NPCSoundID + // 13 m_particleColorID + // 14 m_creatureGeosetData + // 15 m_objectEffectPackageID }; struct CreatureFamilyEntry { - uint32 ID; // 0 - float minScale; // 1 - uint32 minScaleLevel; // 2 0/1 - float maxScale; // 3 - uint32 maxScaleLevel; // 4 0/60 - uint32 skillLine[2]; // 5-6 - uint32 petFoodMask; // 7 - char* Name[16]; // 8-23 - // 24 string flags, unused - // 25 icon, unused + uint32 ID; // 0 m_ID + float minScale; // 1 m_minScale + uint32 minScaleLevel; // 2 m_minScaleLevel + float maxScale; // 3 m_maxScale + uint32 maxScaleLevel; // 4 m_maxScaleLevel + uint32 skillLine[2]; // 5-6 m_skillLine + uint32 petFoodMask; // 7 m_petFoodMask + int32 petTalentType; // 8 m_petTalentType + // 9 m_categoryEnumID + char* Name[16]; // 10-25 m_name_lang + // 26 string flags + // 27 m_iconFile }; struct CreatureSpellDataEntry { - uint32 ID; // 0 - //uint32 spellId[4]; // 1-4 hunter pet learned spell (for later use) + uint32 ID; // 0 m_ID + //uint32 spellId[4]; // 1-4 m_spells[4] + //uint32 availability[4]; // 4-7 m_availability[4] +}; + +struct CreatureTypeEntry +{ + uint32 ID; // 0 m_ID + //char* Name[16]; // 1-16 name + // 17 string flags + //uint32 no_expirience; // 18 no exp? critters, non-combat pets, gas cloud. }; struct DurabilityCostsEntry @@ -204,41 +689,35 @@ struct DurabilityQualityEntry struct EmotesTextEntry { - uint32 Id; - uint32 textid; + uint32 Id; + uint32 textid; }; struct FactionEntry { - uint32 ID; // 0 - int32 reputationListID; // 1 - uint32 BaseRepRaceMask[4]; // 2-5 Base reputation race masks (see enum Races) - uint32 BaseRepClassMask[4]; // 6-9 Base reputation class masks (see enum Classes) - int32 BaseRepValue[4]; // 10-13 Base reputation values - uint32 ReputationFlags[4]; // 14-17 Default flags to apply - uint32 team; // 18 enum Team - char* name[16]; // 19-34 - // 35 string flags, unused - //char* description[16]; // 36-51 unused - // 52 string flags, unused + uint32 ID; // 0 m_ID + int32 reputationListID; // 1 m_reputationIndex + uint32 BaseRepRaceMask[4]; // 2-5 m_reputationRaceMask + uint32 BaseRepClassMask[4]; // 6-9 m_reputationClassMask + int32 BaseRepValue[4]; // 10-13 m_reputationBase + uint32 ReputationFlags[4]; // 14-17 m_reputationFlags + uint32 team; // 18 m_parentFactionID + char* name[16]; // 19-34 m_name_lang + // 35 string flags + //char* description[16]; // 36-51 m_description_lang + // 52 string flags }; struct FactionTemplateEntry { - uint32 ID; // 0 - uint32 faction; // 1 - uint32 factionFlags; // 2 specific flags for that faction - uint32 ourMask; // 3 if mask set (see FactionMasks) then faction included in masked team - uint32 friendlyMask; // 4 if mask set (see FactionMasks) then faction friendly to masked team - uint32 hostileMask; // 5 if mask set (see FactionMasks) then faction hostile to masked team - uint32 enemyFaction1; // 6 - uint32 enemyFaction2; // 7 - uint32 enemyFaction3; // 8 - uint32 enemyFaction4; // 9 - uint32 friendFaction1; // 10 - uint32 friendFaction2; // 11 - uint32 friendFaction3; // 12 - uint32 friendFaction4; // 13 + uint32 ID; // 0 m_ID + uint32 faction; // 1 m_faction + uint32 factionFlags; // 2 m_flags + uint32 ourMask; // 3 m_factionGroup + uint32 friendlyMask; // 4 m_friendGroup + uint32 hostileMask; // 5 m_enemyGroup + uint32 enemyFaction[4]; // 6 m_enemies[4] + uint32 friendFaction[4]; // 10 m_friend[4] //------------------------------------------------------- end structure // helpers @@ -246,9 +725,9 @@ struct FactionTemplateEntry { if(ID == entry.ID) return true; - if(enemyFaction1 == entry.faction || enemyFaction2 == entry.faction || enemyFaction3 == entry.faction || enemyFaction4 == entry.faction ) + if(enemyFaction[0] == entry.faction || enemyFaction[1] == entry.faction || enemyFaction[2] == entry.faction || enemyFaction[3] == entry.faction ) return false; - if(friendFaction1 == entry.faction || friendFaction2 == entry.faction || friendFaction3 == entry.faction || friendFaction4 == entry.faction ) + if(friendFaction[0] == entry.faction || friendFaction[1] == entry.faction || friendFaction[2] == entry.faction || friendFaction[3] == entry.faction ) return true; return (friendlyMask & entry.ourMask) || (ourMask & entry.friendlyMask); } @@ -256,14 +735,14 @@ struct FactionTemplateEntry { if(ID == entry.ID) return false; - if(enemyFaction1 == entry.faction || enemyFaction2 == entry.faction || enemyFaction3 == entry.faction || enemyFaction4 == entry.faction ) + if(enemyFaction[0] == entry.faction || enemyFaction[1] == entry.faction || enemyFaction[2] == entry.faction || enemyFaction[3] == entry.faction ) return true; - if(friendFaction1 == entry.faction || friendFaction2 == entry.faction || friendFaction3 == entry.faction || friendFaction4 == entry.faction ) + if(friendFaction[0] == entry.faction || friendFaction[1] == entry.faction || friendFaction[2] == entry.faction || friendFaction[3] == entry.faction ) return false; return (hostileMask & entry.ourMask) != 0; } bool IsHostileToPlayers() const { return (hostileMask & FACTION_MASK_PLAYER) !=0; } - bool IsNeutralToAll() const { return hostileMask == 0 && friendlyMask == 0 && enemyFaction1==0 && enemyFaction2==0 && enemyFaction3==0 && enemyFaction4==0; } + bool IsNeutralToAll() const { return hostileMask == 0 && friendlyMask == 0 && enemyFaction[0]==0 && enemyFaction[1]==0 && enemyFaction[2]==0 && enemyFaction[3]==0; } bool IsContestedGuardFaction() const { return (factionFlags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD)!=0; } }; @@ -274,9 +753,29 @@ struct GemPropertiesEntry uint32 color; }; +struct GlyphPropertiesEntry +{ + uint32 Id; + uint32 SpellId; + uint32 TypeFlags; + uint32 Unk1; // GlyphIconId (SpellIcon.dbc) +}; + +struct GlyphSlotEntry +{ + uint32 Id; + uint32 TypeFlags; + uint32 Order; +}; + // All Gt* DBC store data for 100 levels, some by 100 per class/race #define GT_MAX_LEVEL 100 +struct GtBarberShopCostBaseEntry +{ + float cost; +}; + struct GtCombatRatingsEntry { float ratio; @@ -324,24 +823,38 @@ struct GtRegenMPPerSptEntry struct ItemEntry { - uint32 ID; - uint32 DisplayId; - uint32 InventoryType; - uint32 Sheath; + uint32 ID; // 0 + uint32 Class; // 1 + //uint32 SubClass; // 2 some items have strnage subclasses + int32 Unk0; // 3 + int32 Material; // 4 + uint32 DisplayId; // 5 + uint32 InventoryType; // 6 + uint32 Sheath; // 7 }; struct ItemDisplayInfoEntry { - uint32 ID; - uint32 randomPropertyChance; + uint32 ID; // 0 m_ID + // 1 m_modelName[2] + // 2 m_modelTexture[2] + // 3 m_inventoryIcon + // 4 m_geosetGroup[3] + // 5 m_flags + // 6 m_spellVisualID + // 7 m_groupSoundIndex + // 8 m_helmetGeosetVis[2] + // 9 m_texture[2] + // 10 m_itemVisual[8] + // 11 m_particleColorID }; //struct ItemCondExtCostsEntry //{ // uint32 ID; -// uint32 condExtendedCost; // ItemPrototype::CondExtendedCost -// uint32 itemextendedcostentry; // ItemPrototype::ExtendedCost -// uint32 arenaseason; // arena season number(1-4) +// uint32 condExtendedCost; // ItemPrototype::CondExtendedCost +// uint32 itemextendedcostentry; // ItemPrototype::ExtendedCost +// uint32 arenaseason; // arena season number(1-4) //}; struct ItemExtendedCostEntry @@ -356,47 +869,42 @@ struct ItemExtendedCostEntry struct ItemRandomPropertiesEntry { - uint32 ID; // 0 - //char* internalName // 1 unused - uint32 enchant_id[3]; // 2-4 - // 5-6 unused, 0 only values, reserved for additional enchantments? - //char* nameSuffix[16] // 7-22, unused - // 23 nameSufix flags, unused + uint32 ID; // 0 m_ID + //char* internalName // 1 m_Name + uint32 enchant_id[5]; // 2-6 m_Enchantment + //char* nameSuffix[16] // 7-22 m_name_lang + // 23 name flags }; struct ItemRandomSuffixEntry { - uint32 ID; // 0 - //char* name[16] // 1-16 unused - // 17, name flags, unused - // 18 unused - uint32 enchant_id[3]; // 19-21 - uint32 prefix[3]; // 22-24 + uint32 ID; // 0 m_ID + //char* name[16] // 1-16 m_name_lang + // 17, name flags + // 18 m_internalName + uint32 enchant_id[5]; // 19-21 m_enchantment + uint32 prefix[5]; // 22-24 m_allocationPct }; struct ItemSetEntry { - //uint32 id // 0 item set ID - char* name[16]; // 1-16 + //uint32 id // 0 m_ID + char* name[16]; // 1-16 m_name_lang // 17 string flags, unused - // 18-28 items from set, but not have all items listed, use ItemPrototype::ItemSet instead - // 29-34 unused - uint32 spells[8]; // 35-42 - uint32 items_to_triggerspell[8]; // 43-50 - uint32 required_skill_id; // 51 - uint32 required_skill_value; // 52 + //uint32 itemId[17]; // 18-34 m_itemID + uint32 spells[8]; // 35-42 m_setSpellID + uint32 items_to_triggerspell[8]; // 43-50 m_setThreshold + uint32 required_skill_id; // 51 m_requiredSkill + uint32 required_skill_value; // 52 m_requiredSkillRank }; struct LockEntry { - uint32 ID; // 0 - uint32 keytype[5]; // 1-5 - // 6-8, not used - uint32 key[5]; // 9-13 - // 14-16, not used - uint32 requiredminingskill; // 17 - uint32 requiredlockskill; // 18 - // 19-32, not used + uint32 ID; // 0 m_ID + uint32 Type[8]; // 1-8 m_Type + uint32 Index[8]; // 9-16 m_Index + uint32 Skill[8]; // 17-24 m_Skill + //uint32 Action[8]; // 25-32 m_Action }; struct MailTemplateEntry @@ -409,35 +917,34 @@ struct MailTemplateEntry struct MapEntry { - uint32 MapID; // 0 + uint32 MapID; // 0 //char* internalname; // 1 unused - uint32 map_type; // 2 - // 3 unused - char* name[16]; // 4-19 + uint32 map_type; // 2 + // 3 0 or 1 for battlegrounds (not arenas) + char* name[16]; // 4-19 // 20 name flags, unused - // 21-23 unused (something PvPZone related - levels?) - // 24-26 - uint32 linked_zone; // 27 common zone for instance and continent map - //char* hordeIntro // 28-43 text for PvP Zones - // 44 intro text flags - //char* allianceIntro // 45-60 text for PvP Zones - // 46 intro text flags - // 47-61 not used - uint32 multimap_id; // 62 - // 63-65 not used - //chat* unknownText1 // 66-81 unknown empty text fields, possible normal Intro text. - // 82 text flags - //chat* heroicIntroText // 83-98 heroic mode requirement text - // 99 text flags - //chat* unknownText2 // 100-115 unknown empty text fields - // 116 text flags - int32 entrance_map; // 117 map_id of entrance map - float entrance_x; // 118 entrance x coordinate (if exist single entry) - float entrance_y; // 119 entrance y coordinate (if exist single entry) - uint32 resetTimeRaid; // 120 - uint32 resetTimeHeroic; // 121 - // 122-123 - uint32 addon; // 124 (0-original maps,1-tbc addon) + uint32 linked_zone; // 21 common zone for instance and continent map + //char* hordeIntro[16]; // 23-37 text for PvP Zones + // 38 intro text flags + //char* allianceIntro[16]; // 39-54 text for PvP Zones + // 55 intro text flags + uint32 multimap_id; // 56 + // 57 + //chat* unknownText1[16]; // 58-73 unknown empty text fields, possible normal Intro text. + // 74 text flags + //chat* heroicIntroText[16]; // 75-90 heroic mode requirement text + // 91 text flags + //chat* unknownText2[16]; // 92-107 unknown empty text fields + // 108 text flags + int32 entrance_map; // 109 map_id of entrance map + float entrance_x; // 110 entrance x coordinate (if exist single entry) + float entrance_y; // 111 entrance y coordinate (if exist single entry) + uint32 resetTimeRaid; // 112 + uint32 resetTimeHeroic; // 113 + // 114 all 0 + // 115 -1, 0 and 720 + uint32 addon; // 116 (0-original maps,1-tbc addon) + // 117 some kind of time? // Helpers uint32 Expansion() const { return addon; } @@ -449,22 +956,29 @@ struct MapEntry bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; } bool IsBattleArena() const { return map_type == MAP_ARENA; } bool IsBattleGroundOrArena() const { return map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; } - bool SupportsHeroicMode() const { return resetTimeHeroic && !resetTimeRaid; } + bool SupportsHeroicMode() const { return resetTimeHeroic != 0; } bool HasResetTime() const { return resetTimeHeroic || resetTimeRaid; } bool IsMountAllowed() const { return !IsDungeon() || - MapID==568 || MapID==309 || MapID==209 || MapID==534 || - MapID==560 || MapID==509 || MapID==269; + MapID==209 || MapID==269 || MapID==309 || // TanarisInstance, CavernsOfTime, Zul'gurub + MapID==509 || MapID==534 || MapID==560 || // AhnQiraj, HyjalPast, HillsbradPast + MapID==568 || MapID==580 || MapID==615 || // ZulAman, Sunwell Plateau, Obsidian Sanctrum + MapID==616; // Eye Of Eternity + } + + bool IsContinent() const + { + return MapID == 0 || MapID == 1 || MapID == 530 || MapID == 571; } }; struct QuestSortEntry { - uint32 id; // 0, sort id - //char* name[16]; // 1-16, unused - // 17 name flags, unused + uint32 id; // 0 m_ID + //char* name[16]; // 1-16 m_SortName_lang + // 17 name flags }; struct RandomPropertiesPointsEntry @@ -476,172 +990,198 @@ struct RandomPropertiesPointsEntry uint32 UncommonPropertiesPoints[5]; // 12-16 }; +struct ScalingStatDistributionEntry +{ + uint32 Id; + uint32 StatMod[10]; + uint32 Modifier[10]; + uint32 MaxLevel; +}; + +struct ScalingStatValuesEntry +{ + uint32 Id; + uint32 Level; + uint32 Multiplier[17]; +}; + //struct SkillLineCategoryEntry{ -// uint32 id; // 0 hidden key -// char* name[16]; // 1 - 17 Category name -// // 18 string flag -// uint32 displayOrder; // Display order in character tab +// uint32 id; // 0 m_ID +// char* name[16]; // 1-17 m_name_lang +// // 18 string flag +// uint32 displayOrder; // 19 m_sortIndex //}; //struct SkillRaceClassInfoEntry{ -// uint32 id; // 0 -// uint32 skillId; // 1 present some refrences to unknown skill -// uint32 raceMask; // 2 -// uint32 classMask; // 3 -// uint32 flags; // 4 mask for some thing -// uint32 reqLevel; // 5 -// uint32 skillTierId; // 6 -// uint32 skillCostID; // 7 +// uint32 id; // 0 m_ID +// uint32 skillId; // 1 m_skillID +// uint32 raceMask; // 2 m_raceMask +// uint32 classMask; // 3 m_classMask +// uint32 flags; // 4 m_flags +// uint32 reqLevel; // 5 m_minLevel +// uint32 skillTierId; // 6 m_skillTierID +// uint32 skillCostID; // 7 m_skillCostIndex //}; //struct SkillTiersEntry{ -// uint32 id; // 0 -// uint32 skillValue[16]; // 1-17 unknown possibly add value on learn? -// uint32 maxSkillValue[16]; // Max value for rank +// uint32 id; // 0 m_ID +// uint32 skillValue[16]; // 1-17 m_cost +// uint32 maxSkillValue[16]; // 18-32 m_valueMax //}; struct SkillLineEntry { - uint32 id; // 0 - uint32 categoryId; // 1 (index from SkillLineCategory.dbc) - //uint32 skillCostID; // 2 not used - char* name[16]; // 3-18 - // 19 string flags, not used - //char* description[16]; // 20-35, not used - // 36 string flags, not used - uint32 spellIcon; // 37 + uint32 id; // 0 m_ID + int32 categoryId; // 1 m_categoryID + //uint32 skillCostID; // 2 m_skillCostsID + char* name[16]; // 3-18 m_displayName_lang + // 19 string flags + //char* description[16]; // 20-35 m_description_lang + // 36 string flags + uint32 spellIcon; // 37 m_spellIconID + //char* alternateVerb[16]; // 38-53 m_alternateVerb_lang + // 54 string flags + // 55 m_canLink }; struct SkillLineAbilityEntry { - uint32 id; // 0, INDEX - uint32 skillId; // 1 - uint32 spellId; // 2 - uint32 racemask; // 3 - uint32 classmask; // 4 - //uint32 racemaskNot; // 5 always 0 in 2.4.2 - //uint32 classmaskNot; // 6 always 0 in 2.4.2 - uint32 req_skill_value; // 7 for trade skill.not for training. - uint32 forward_spellid; // 8 - uint32 learnOnGetSkill; // 9 can be 1 or 2 for spells learned on get skill - uint32 max_value; // 10 - uint32 min_value; // 11 - // 12-13, unknown, always 0 - uint32 reqtrainpoints; // 14 + uint32 id; // 0 m_ID + uint32 skillId; // 1 m_skillLine + uint32 spellId; // 2 m_spell + uint32 racemask; // 3 m_raceMask + uint32 classmask; // 4 m_classMask + //uint32 racemaskNot; // 5 m_excludeRace + //uint32 classmaskNot; // 6 m_excludeClass + uint32 req_skill_value; // 7 m_minSkillLineRank + uint32 forward_spellid; // 8 m_supercededBySpell + uint32 learnOnGetSkill; // 9 m_acquireMethod + uint32 max_value; // 10 m_trivialSkillLineRankHigh + uint32 min_value; // 11 m_trivialSkillLineRankLow + //uint32 characterPoints[2]; // 12-13 m_characterPoints[2] }; struct SoundEntriesEntry { - uint32 Id; // 0, sound id - //uint32 Type; // 1, sound type (10 generally for creature, etc) - //char* InternalName; // 2, internal name, for use in lookup command for example - //char* FileName[10]; // 3-12, file names - //uint32 Unk13[10]; // 13-22, linked with file names? - //char* Path; // 23 - // 24-28, unknown + uint32 Id; // 0 m_ID + //uint32 Type; // 1 m_soundType + //char* InternalName; // 2 m_name + //char* FileName[10]; // 3-12 m_File[10] + //uint32 Unk13[10]; // 13-22 m_Freq[10] + //char* Path; // 23 m_DirectoryBase + // 24 m_volumeFloat + // 25 m_flags + // 26 m_minDistance + // 27 m_distanceCutoff + // 28 m_EAXDef }; struct SpellEntry { - uint32 Id; // 0 normally counted from 0 field (but some tools start counting from 1, check this before tool use for data view!) - uint32 Category; // 1 - //uint32 castUI // 2 not used - uint32 Dispel; // 3 - uint32 Mechanic; // 4 - uint32 Attributes; // 5 - uint32 AttributesEx; // 6 - uint32 AttributesEx2; // 7 - uint32 AttributesEx3; // 8 - uint32 AttributesEx4; // 9 - uint32 AttributesEx5; // 10 - //uint32 AttributesEx6; // 11 not used - uint32 Stances; // 12 - uint32 StancesNot; // 13 - uint32 Targets; // 14 - uint32 TargetCreatureType; // 15 - uint32 RequiresSpellFocus; // 16 - uint32 FacingCasterFlags; // 17 - uint32 CasterAuraState; // 18 - uint32 TargetAuraState; // 19 - uint32 CasterAuraStateNot; // 20 - uint32 TargetAuraStateNot; // 21 - uint32 CastingTimeIndex; // 22 - uint32 RecoveryTime; // 23 - uint32 CategoryRecoveryTime; // 24 - uint32 InterruptFlags; // 25 - uint32 AuraInterruptFlags; // 26 - uint32 ChannelInterruptFlags; // 27 - uint32 procFlags; // 28 - uint32 procChance; // 29 - uint32 procCharges; // 30 - uint32 maxLevel; // 31 - uint32 baseLevel; // 32 - uint32 spellLevel; // 33 - uint32 DurationIndex; // 34 - uint32 powerType; // 35 - uint32 manaCost; // 36 - uint32 manaCostPerlevel; // 37 - uint32 manaPerSecond; // 38 - uint32 manaPerSecondPerLevel; // 39 - uint32 rangeIndex; // 40 - float speed; // 41 - //uint32 modalNextSpell; // 42 - uint32 StackAmount; // 43 - uint32 Totem[2]; // 44-45 - int32 Reagent[8]; // 46-53 - uint32 ReagentCount[8]; // 54-61 - int32 EquippedItemClass; // 62 (value) - int32 EquippedItemSubClassMask; // 63 (mask) - int32 EquippedItemInventoryTypeMask; // 64 (mask) - uint32 Effect[3]; // 65-67 - int32 EffectDieSides[3]; // 68-70 - uint32 EffectBaseDice[3]; // 71-73 - float EffectDicePerLevel[3]; // 74-76 - float EffectRealPointsPerLevel[3]; // 77-79 - int32 EffectBasePoints[3]; // 80-82 (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints) - uint32 EffectMechanic[3]; // 83-85 - uint32 EffectImplicitTargetA[3]; // 86-88 - uint32 EffectImplicitTargetB[3]; // 89-91 - uint32 EffectRadiusIndex[3]; // 92-94 - spellradius.dbc - uint32 EffectApplyAuraName[3]; // 95-97 - uint32 EffectAmplitude[3]; // 98-100 - float EffectMultipleValue[3]; // 101-103 - uint32 EffectChainTarget[3]; // 104-106 - uint32 EffectItemType[3]; // 107-109 - int32 EffectMiscValue[3]; // 110-112 - int32 EffectMiscValueB[3]; // 113-115 - uint32 EffectTriggerSpell[3]; // 116-118 - float EffectPointsPerComboPoint[3]; // 119-121 - uint32 SpellVisual; // 122 - // 123 not used - uint32 SpellIconID; // 124 - uint32 activeIconID; // 125 - //uint32 spellPriority; // 126 - char* SpellName[16]; // 127-142 - //uint32 SpellNameFlag; // 143 - char* Rank[16]; // 144-159 - //uint32 RankFlags; // 160 - //char* Description[16]; // 161-176 not used - //uint32 DescriptionFlags; // 177 not used - //char* ToolTip[16]; // 178-193 not used - //uint32 ToolTipFlags; // 194 not used - uint32 ManaCostPercentage; // 195 - uint32 StartRecoveryCategory; // 196 - uint32 StartRecoveryTime; // 197 - uint32 MaxTargetLevel; // 198 - uint32 SpellFamilyName; // 199 - uint64 SpellFamilyFlags; // 200+201 - uint32 MaxAffectedTargets; // 202 - uint32 DmgClass; // 203 defenseType - uint32 PreventionType; // 204 - //uint32 StanceBarOrder; // 205 not used - float DmgMultiplier[3]; // 206-208 - //uint32 MinFactionId; // 209 not used, and 0 in 2.4.2 - //uint32 MinReputation; // 210 not used, and 0 in 2.4.2 - //uint32 RequiredAuraVision; // 211 not used - uint32 TotemCategory[2]; // 212-213 - uint32 AreaId; // 214 - uint32 SchoolMask; // 215 school mask + uint32 Id; // 0 m_ID + uint32 Category; // 1 m_category + uint32 Dispel; // 2 m_dispelType + uint32 Mechanic; // 3 m_mechanic + uint32 Attributes; // 4 m_attribute + uint32 AttributesEx; // 5 m_attributesEx + uint32 AttributesEx2; // 6 m_attributesExB + uint32 AttributesEx3; // 7 m_attributesExC + uint32 AttributesEx4; // 8 m_attributesExD + uint32 AttributesEx5; // 9 m_attributesExE + //uint32 AttributesEx6; // 10 m_attributesExF not used + uint32 Stances; // 11 m_shapeshiftMask + uint32 StancesNot; // 12 m_shapeshiftExclude + uint32 Targets; // 13 m_targets + uint32 TargetCreatureType; // 14 m_targetCreatureType + uint32 RequiresSpellFocus; // 15 m_requiresSpellFocus + uint32 FacingCasterFlags; // 16 m_facingCasterFlags + uint32 CasterAuraState; // 17 m_casterAuraState + uint32 TargetAuraState; // 18 m_targetAuraState + uint32 CasterAuraStateNot; // 19 m_excludeCasterAuraState + uint32 TargetAuraStateNot; // 20 m_excludeTargetAuraState + uint32 casterAuraSpell; // 21 m_casterAuraSpell + uint32 targetAuraSpell; // 22 m_targetAuraSpell + uint32 excludeCasterAuraSpell; // 23 m_excludeCasterAuraSpell + uint32 excludeTargetAuraSpell; // 24 m_excludeTargetAuraSpell + uint32 CastingTimeIndex; // 25 m_castingTimeIndex + uint32 RecoveryTime; // 26 m_recoveryTime + uint32 CategoryRecoveryTime; // 27 m_categoryRecoveryTime + uint32 InterruptFlags; // 28 m_interruptFlags + uint32 AuraInterruptFlags; // 29 m_auraInterruptFlags + uint32 ChannelInterruptFlags; // 30 m_channelInterruptFlags + uint32 procFlags; // 31 m_procTypeMask + uint32 procChance; // 32 m_procChance + uint32 procCharges; // 33 m_procCharges + uint32 maxLevel; // 34 m_maxLevel + uint32 baseLevel; // 35 m_baseLevel + uint32 spellLevel; // 36 m_spellLevel + uint32 DurationIndex; // 37 m_durationIndex + uint32 powerType; // 38 m_powerType + uint32 manaCost; // 39 m_manaCost + uint32 manaCostPerlevel; // 40 m_manaCostPerLevel + uint32 manaPerSecond; // 41 m_manaPerSecond + uint32 manaPerSecondPerLevel; // 42 m_manaPerSecondPerLeve + uint32 rangeIndex; // 43 m_rangeIndex + float speed; // 44 m_speed + //uint32 modalNextSpell; // 45 m_modalNextSpell not used + uint32 StackAmount; // 46 m_cumulativeAura + uint32 Totem[2]; // 47-48 m_totem + int32 Reagent[8]; // 49-56 m_reagent + uint32 ReagentCount[8]; // 57-64 m_reagentCount + int32 EquippedItemClass; // 65 m_equippedItemClass (value) + int32 EquippedItemSubClassMask; // 66 m_equippedItemSubclass (mask) + int32 EquippedItemInventoryTypeMask; // 67 m_equippedItemInvTypes (mask) + uint32 Effect[3]; // 68-70 m_effect + int32 EffectDieSides[3]; // 71-73 m_effectDieSides + uint32 EffectBaseDice[3]; // 74-76 m_effectBaseDice + float EffectDicePerLevel[3]; // 77-79 m_effectDicePerLevel + float EffectRealPointsPerLevel[3]; // 80-82 m_effectRealPointsPerLevel + int32 EffectBasePoints[3]; // 83-85 m_effectBasePoints (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints) + uint32 EffectMechanic[3]; // 86-88 m_effectMechanic + uint32 EffectImplicitTargetA[3]; // 89-91 m_implicitTargetA + uint32 EffectImplicitTargetB[3]; // 92-94 m_implicitTargetB + uint32 EffectRadiusIndex[3]; // 95-97 m_effectRadiusIndex - spellradius.dbc + uint32 EffectApplyAuraName[3]; // 98-100 m_effectAura + uint32 EffectAmplitude[3]; // 101-103 m_effectAuraPeriod + float EffectMultipleValue[3]; // 104-106 m_effectAmplitude + uint32 EffectChainTarget[3]; // 107-109 m_effectChainTargets + uint32 EffectItemType[3]; // 110-112 m_effectItemType + int32 EffectMiscValue[3]; // 113-115 m_effectMiscValue + int32 EffectMiscValueB[3]; // 116-118 m_effectMiscValueB + uint32 EffectTriggerSpell[3]; // 119-121 m_effectTriggerSpell + float EffectPointsPerComboPoint[3]; // 122-124 m_effectPointsPerCombo + flag96 EffectSpellClassMask[3]; // + uint32 SpellVisual[2]; // 134-135 m_spellVisualID + uint32 SpellIconID; // 136 m_spellIconID + uint32 activeIconID; // 137 m_activeIconID + //uint32 spellPriority; // 138 not used + char* SpellName[16]; // 139-154 m_name_lang + //uint32 SpellNameFlag; // 155 not used + char* Rank[16]; // 156-171 m_nameSubtext_lang + //uint32 RankFlags; // 172 not used + //char* Description[16]; // 173-188 m_description_lang not used + //uint32 DescriptionFlags; // 189 not used + //char* ToolTip[16]; // 190-205 m_auraDescription_lang not used + //uint32 ToolTipFlags; // 206 not used + uint32 ManaCostPercentage; // 207 m_manaCostPct + uint32 StartRecoveryCategory; // 208 m_startRecoveryCategory + uint32 StartRecoveryTime; // 209 m_startRecoveryTime + uint32 MaxTargetLevel; // 210 m_maxTargetLevel + uint32 SpellFamilyName; // 211 m_spellClassSet + flag96 SpellFamilyFlags; // 212-214 + uint32 MaxAffectedTargets; // 215 m_maxTargets + uint32 DmgClass; // 216 m_defenseType + uint32 PreventionType; // 217 m_preventionType + //uint32 StanceBarOrder; // 218 m_stanceBarOrder not used + float DmgMultiplier[3]; // 219-221 m_effectChainAmplitude + //uint32 MinFactionId; // 222 m_minFactionID not used + //uint32 MinReputation; // 223 m_minReputation not used + //uint32 RequiredAuraVision; // 224 m_requiredAuraVision not used + uint32 TotemCategory[2]; // 225-226 m_requiredTotemCategoryID + int32 AreaGroupId; // 227 m_requiredAreaGroupId + uint32 SchoolMask; // 228 m_schoolMask + uint32 runeCostID; // 229 m_runeCostID + //uint32 spellMissileID; // 230 m_spellMissileID not used private: // prevent creating custom entries (copy data from original in fact) @@ -690,6 +1230,16 @@ struct SpellRangeEntry uint32 type; }; +struct SpellRuneCostEntry +{ + uint32 ID; // 0 + uint32 RuneCost[3]; // 1-3 (0=blood, 1=frost, 2=unholy) + uint32 runePowerGain; // 4 + + bool NoRuneCost() const { return RuneCost[0] == 0 && RuneCost[1] == 0 && RuneCost[2] == 0; } + bool NoRunicPowerGain() const { return runePowerGain == 0; } +}; + struct SpellShapeshiftEntry { uint32 ID; // 0 @@ -722,26 +1272,31 @@ struct SpellDurationEntry struct SpellItemEnchantmentEntry { - uint32 ID; // 0 - uint32 type[3]; // 1-3 - uint32 amount[3]; // 4-6 - //uint32 amount2[3] // 7-9 always same as similar `amount` value - uint32 spellid[3]; // 10-12 - char* description[16]; // 13-29 - // 30 description flags - uint32 aura_id; // 31 - uint32 slot; // 32 - uint32 GemID; // 33 - uint32 EnchantmentCondition; // 34 + uint32 ID; // 0 m_ID + //uint32 charges; // 1 m_charges + uint32 type[3]; // 2-4 m_effect[3] + uint32 amount[3]; // 5-7 m_effectPointsMin[3] + //uint32 amount2[3] // 8-10 m_effectPointsMax[3] + uint32 spellid[3]; // 11-13 m_effectArg[3] + char* description[16]; // 14-29 m_name_lang[16] + //uint32 descriptionFlags; // 30 name flags + uint32 aura_id; // 31 m_itemVisual + uint32 slot; // 32 m_flags + uint32 GemID; // 33 m_src_itemID + uint32 EnchantmentCondition; // 34 m_condition_id + //uint32 requiredSkill; // 35 m_requiredSkillID + //uint32 requiredSkillValue; // 36 m_requiredSkillRank }; struct SpellItemEnchantmentConditionEntry { - uint32 ID; - uint8 Color[5]; - uint8 Comparator[5]; - uint8 CompareColor[5]; - uint32 Value[5]; + uint32 ID; // 0 m_ID + uint8 Color[5]; // 1-5 m_lt_operandType[5] + //uint32 LT_Operand[5]; // 6-10 m_lt_operand[5] + uint8 Comparator[5]; // 11-15 m_operator[5] + uint8 CompareColor[5]; // 15-20 m_rt_operandType[5] + uint32 Value[5]; // 21-25 m_rt_operand[5] + //uint8 Logic[5] // 25-30 m_logic[5] }; struct StableSlotPricesEntry @@ -750,6 +1305,16 @@ struct StableSlotPricesEntry uint32 Price; }; +/*struct SummonPropertiesEntry +{ + uint32 Id; // 0 + uint32 Group; // 1, 0 - can't be controlled?, 1 - something guardian?, 2 - pet?, 3 - something controllable?, 4 - taxi/mount? + uint32 Unk2; // 2, 14 rows > 0 + uint32 Type; // 3, see enum + uint32 Slot; // 4, 0-6 + uint32 Flags; // 5 +};*/ + struct TalentEntry { uint32 TalentID; // 0 @@ -761,53 +1326,59 @@ struct TalentEntry uint32 DependsOn; // 13 index in Talent.dbc (TalentEntry) // 14-15 not used uint32 DependsOnRank; // 16 - // 17-19 not used - uint32 DependsOnSpell; // 20 req.spell + // 17-18 not used + //uint32 unk1; // 19, 0 or 1 + //uint32 unk2; // 20, all 0 + //uint32 unkFlags1; // 21, related to hunter pet talents + //uint32 unkFlags2; // 22, related to hunter pet talents }; struct TalentTabEntry { - uint32 TalentTabID; // 0 - //char* name[16]; // 1-16, unused + uint32 TalentTabID; // 0 + //char* name[16]; // 1-16, unused //uint32 nameFlags; // 17, unused //unit32 spellicon; // 18 // 19 not used - uint32 ClassMask; // 20 - uint32 tabpage; // 21 - //char* internalname; // 22 + uint32 ClassMask; // 20 + uint32 petTalentMask; // 21 + uint32 tabpage; // 22 + //char* internalname; // 23 }; struct TaxiNodesEntry { - uint32 ID; // 0 - uint32 map_id; // 1 - float x; // 2 - float y; // 3 - float z; // 4 - //char* name[16]; // 5-21 - // 22 string flags, unused - uint32 horde_mount_type; // 23 - uint32 alliance_mount_type; // 24 + uint32 ID; // 0 m_ID + uint32 map_id; // 1 m_ContinentID + float x; // 2 m_x + float y; // 3 m_y + float z; // 4 m_z + //char* name[16]; // 5-21 m_Name_lang + // 22 string flags + uint32 MountCreatureID[2]; // 23-24 m_MountCreatureID[2] }; struct TaxiPathEntry { - uint32 ID; - uint32 from; - uint32 to; - uint32 price; + uint32 ID; // 0 m_ID + uint32 from; // 1 m_FromTaxiNode + uint32 to; // 2 m_ToTaxiNode + uint32 price; // 3 m_Cost }; struct TaxiPathNodeEntry { - uint32 path; - uint32 index; - uint32 mapid; - float x; - float y; - float z; - uint32 actionFlag; - uint32 delay; + // 0 m_ID + uint32 path; // 1 m_PathID + uint32 index; // 2 m_NodeIndex + uint32 mapid; // 3 m_ContinentID + float x; // 4 m_LocX + float y; // 5 m_LocY + float z; // 6 m_LocZ + uint32 actionFlag; // 7 m_flags + uint32 delay; // 8 m_delay + // 9 m_arrivalEventID + // 10 m_departureEventID }; struct TotemCategoryEntry @@ -819,16 +1390,100 @@ struct TotemCategoryEntry uint32 categoryMask; // 19 (compatibility mask for same type: different for totems, compatible from high to low for rods) }; +struct VehicleEntry +{ + uint32 m_ID; // 0 + uint32 m_flags; // 1 + float m_turnSpeed; // 2 + float m_pitchSpeed; // 3 + float m_pitchMin; // 4 + float m_pitchMax; // 5 + uint32 m_seatID[8]; // 6-13 + float m_mouseLookOffsetPitch; // 14 + float m_cameraFadeDistScalarMin; // 15 + float m_cameraFadeDistScalarMax; // 16 + float m_cameraPitchOffset; // 17 + int m_powerType[3]; // 18-20 + int m_powerToken[3]; // 21-23 + float m_facingLimitRight; // 24 + float m_facingLimitLeft; // 25 + float m_msslTrgtTurnLingering; // 26 + float m_msslTrgtPitchLingering; // 27 + float m_msslTrgtMouseLingering; // 28 + float m_msslTrgtEndOpacity; // 29 + float m_msslTrgtArcSpeed; // 30 + float m_msslTrgtArcRepeat; // 31 + float m_msslTrgtArcWidth; // 32 + float m_msslTrgtImpactRadius[2]; // 33-34 + char* m_msslTrgtArcTexture; // 35 + char* m_msslTrgtImpactTexture; // 36 + char* m_msslTrgtImpactModel[2]; // 37-38 + float m_cameraYawOffset; // 39 + uint32 m_uiLocomotionType; // 40 + float m_msslTrgtImpactTexRadius; // 41 + uint32 m_uiSeatIndicatorType; // 42 +}; + +struct VehicleSeatEntry +{ + uint32 m_ID; // 0 + uint32 m_flags; // 1 + int32 m_attachmentID; // 2 + float m_attachmentOffsetX; // 3 + float m_attachmentOffsetY; // 4 + float m_attachmentOffsetZ; // 5 + float m_enterPreDelay; // 6 + float m_enterSpeed; // 7 + float m_enterGravity; // 8 + float m_enterMinDuration; // 9 + float m_enterMaxDuration; // 10 + float m_enterMinArcHeight; // 11 + float m_enterMaxArcHeight; // 12 + int32 m_enterAnimStart; // 13 + int32 m_enterAnimLoop; // 14 + int32 m_rideAnimStart; // 15 + int32 m_rideAnimLoop; // 16 + int32 m_rideUpperAnimStart; // 17 + int32 m_rideUpperAnimLoop; // 18 + float m_exitPreDelay; // 19 + float m_exitSpeed; // 20 + float m_exitGravity; // 21 + float m_exitMinDuration; // 22 + float m_exitMaxDuration; // 23 + float m_exitMinArcHeight; // 24 + float m_exitMaxArcHeight; // 25 + int32 m_exitAnimStart; // 26 + int32 m_exitAnimLoop; // 27 + int32 m_exitAnimEnd; // 28 + float m_passengerYaw; // 29 + float m_passengerPitch; // 30 + float m_passengerRoll; // 31 + int32 m_passengerAttachmentID; // 32 + int32 m_vehicleEnterAnim; // 33 + int32 m_vehicleExitAnim; // 34 + int32 m_vehicleRideAnimLoop; // 35 + int32 m_vehicleEnterAnimBone; // 36 + int32 m_vehicleExitAnimBone; // 37 + int32 m_vehicleRideAnimLoopBone; // 38 + float m_vehicleEnterAnimDelay; // 39 + float m_vehicleExitAnimDelay; // 40 + uint32 m_vehicleAbilityDisplay; // 41 + uint32 m_enterUISoundID; // 42 + uint32 m_exitUISoundID; // 43 + int32 m_uiSkin; // 44 + uint32 m_flagsB; // 45 +}; + struct WorldMapAreaEntry { - //uint32 ID; // 0 - uint32 map_id; // 1 - uint32 area_id; // 2 index (continent 0 areas ignored) - //char* internal_name // 3 - float y1; // 4 - float y2; // 5 - float x1; // 6 - float x2; // 7 + //uint32 ID; // 0 + uint32 map_id; // 1 + uint32 area_id; // 2 index (continent 0 areas ignored) + //char* internal_name // 3 + float y1; // 4 + float y2; // 5 + float x1; // 6 + float x2; // 7 int32 virtual_map_id; // 8 -1 (map_id have correct map) other: virtual map where zone show (map_id - where zone in fact internally) }; @@ -843,6 +1498,12 @@ struct WorldSafeLocsEntry // 21 name flags, unused }; +struct WorldMapOverlayEntry +{ + uint32 ID; // 0 + uint32 areatableID; // 2 +}; + // GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform #if defined( __GNUC__ ) #pragma pack() @@ -888,6 +1549,6 @@ struct TaxiPathNode typedef std::vector<TaxiPathNode> TaxiPathNodeList; typedef std::vector<TaxiPathNodeList> TaxiPathNodesByPath; -#define TaxiMaskSize 16 +#define TaxiMaskSize 12 typedef uint32 TaxiMask[TaxiMaskSize]; #endif diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 57a81921d62..643e1828448 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -10,36 +10,41 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxixxxxxx"; +const char Achievementfmt[]="niixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxxi"; +const char AchievementCriteriafmt[]="niiiiiiiixxxxxxxxxxxxxxxxxiixix"; +const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxixxxxxxx"; +const char AreaGroupEntryfmt[]="niiiiiii"; const char AreaTriggerEntryfmt[]="niffffffff"; const char BankBagSlotPricesEntryfmt[]="ni"; -const char BattlemasterListEntryfmt[]="niiixxxxxiiiixxssssssssssssssssxx"; -const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxx"; -// 3*12 new item fields in 3.0.x -//const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +const char BarberShopStyleEntryfmt[]="nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii"; +const char BattlemasterListEntryfmt[]="niiiiiiiiiiiixxxssssssssssssssssxx"; +const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char CharTitlesEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx"; // ChatChannelsEntryfmt, index not used (more compact store) -//const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix"; -const char ChrClassesEntryfmt[]="nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix"; +const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii"; const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; -const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxx"; -const char CreatureFamilyfmt[]="nfifiiiissssssssssssssssxx"; +const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxxxx"; +const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx"; const char CreatureSpellDatafmt[]="nxxxxxxxx"; +const char CreatureTypefmt[]="nxxxxxxxxxxxxxxxxxx"; const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii"; const char DurabilityQualityfmt[]="nf"; const char EmoteEntryfmt[]="nxixxxxxxxxxxxxxxxx"; const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiissssssssssssssssxxxxxxxxxxxxxxxxxx"; const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii"; const char GemPropertiesEntryfmt[]="nixxi"; +const char GlyphPropertiesfmt[]="niii"; +const char GlyphSlotfmt[]="nii"; +const char GtBarberShopCostBasefmt[]="f"; const char GtCombatRatingsfmt[]="f"; const char GtChanceToMeleeCritBasefmt[]="f"; const char GtChanceToMeleeCritfmt[]="f"; @@ -49,36 +54,44 @@ const char GtOCTRegenHPfmt[]="f"; //const char GtOCTRegenMPfmt[]="f"; const char GtRegenHPPerSptfmt[]="f"; const char GtRegenMPPerSptfmt[]="f"; -const char Itemfmt[]="niii"; +const char Itemfmt[]="nixiiiii"; //const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx"; //const char ItemCondExtCostsEntryfmt[]="xiii"; -const char ItemExtendedCostEntryfmt[]="niiiiiiiiiiiii"; -const char ItemRandomPropertiesfmt[]="nxiiixxxxxxxxxxxxxxxxxxx"; -const char ItemRandomSuffixfmt[]="nxxxxxxxxxxxxxxxxxxiiiiii"; +const char ItemExtendedCostEntryfmt[]="niiiiiiiiiiiiix"; +const char ItemRandomPropertiesfmt[]="nxiiiiixxxxxxxxxxxxxxxxx"; +const char ItemRandomSuffixfmt[]="nxxxxxxxxxxxxxxxxxxiiiiiiiiii"; const char ItemSetEntryfmt[]="dssssssssssssssssxxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii"; -const char LockEntryfmt[]="niiiiixxxiiiiixxxiixxxxxxxxxxxxxx"; +const char LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx"; const char MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; -const char MapEntryfmt[]="nxixssssssssssssssssxxxxxxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiffiixxi"; +const char MapEntryfmt[]="nxixssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiffiixxix"; const char QuestSortEntryfmt[]="nxxxxxxxxxxxxxxxxx"; const char RandomPropertiesPointsfmt[]="niiiiiiiiiiiiiii"; -const char SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxi"; -const char SkillLineAbilityfmt[]="niiiixxiiiiixxi"; +const char ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiii"; +const char ScalingStatValuesfmt[]="iniiiiiiiiiiiiiiiii"; +const char SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxx"; +const char SkillLineAbilityfmt[]="niiiixxiiiiixx"; const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char SpellCastTimefmt[]="nixx"; const char SpellDurationfmt[]="niii"; -const char SpellEntryfmt[]="nixiiiiiiiixiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffixiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiixfffxxxiiii"; +const char SpellEntryfmt[]="niiiiiiiiixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiix"; const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx"; -const char SpellItemEnchantmentfmt[]="niiiiiixxxiiissssssssssssssssxiiii"; +const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiixx"; const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; const char SpellRadiusfmt[]="nfxf"; -const char SpellRangefmt[]="nffixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +const char SpellRangefmt[]="nfxfxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +const char SpellRuneCostfmt[]="niiii"; const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxx"; const char StableSlotPricesfmt[] = "ni"; -const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxi"; -const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiix"; +//const char SummonPropertiesfmt[] = "niiiii"; +const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx"; +const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiiix"; const char TaxiNodesEntryfmt[]="nifffxxxxxxxxxxxxxxxxxii"; const char TaxiPathEntryfmt[]="niii"; const char TaxiPathNodeEntryfmt[]="diiifffiixx"; const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; -const char WorldMapAreaEntryfmt[]="xinxffffi"; +const char VehicleEntryfmt[]="niffffiiiiiiiiffffiiiiiifffffffffffssssfifi"; +const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiii"; +const char WorldMapAreaEntryfmt[]="xinxffffix"; const char WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx"; +const char WorldMapOverlayEntryfmt[]="nxixxxxxxxxxxxxxx"; + diff --git a/src/shared/Database/Database.cpp b/src/shared/Database/Database.cpp index 4623deacbed..5d7f5bf473e 100644 --- a/src/shared/Database/Database.cpp +++ b/src/shared/Database/Database.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index 7e64fbebb55..beff0fb740a 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,7 +33,7 @@ class SqlQueryHolder; typedef UNORDERED_MAP<ZThread::ThreadImpl*, SqlTransaction*> TransactionQueues; typedef UNORDERED_MAP<ZThread::ThreadImpl*, SqlResultQueue*> QueryQueues; -#define MAX_QUERY_LEN 1024 +#define MAX_QUERY_LEN 32*1024 class TRINITY_DLL_SPEC Database { diff --git a/src/shared/Database/DatabaseEnv.h b/src/shared/Database/DatabaseEnv.h index fe565cde7a6..df1f51adbe7 100644 --- a/src/shared/Database/DatabaseEnv.h +++ b/src/shared/Database/DatabaseEnv.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/DatabaseImpl.h b/src/shared/Database/DatabaseImpl.h index 244f52d0106..c9a02a0a4a1 100644 --- a/src/shared/Database/DatabaseImpl.h +++ b/src/shared/Database/DatabaseImpl.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/DatabaseMysql.cpp b/src/shared/Database/DatabaseMysql.cpp index 0fae83caadf..7e67861d883 100644 --- a/src/shared/Database/DatabaseMysql.cpp +++ b/src/shared/Database/DatabaseMysql.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/DatabaseMysql.h b/src/shared/Database/DatabaseMysql.h index ee800fdf22e..6dbaf4a59ab 100644 --- a/src/shared/Database/DatabaseMysql.h +++ b/src/shared/Database/DatabaseMysql.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/DatabasePostgre.cpp b/src/shared/Database/DatabasePostgre.cpp index 6a172bb12a0..8f8cf95b429 100644 --- a/src/shared/Database/DatabasePostgre.cpp +++ b/src/shared/Database/DatabasePostgre.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/DatabasePostgre.h b/src/shared/Database/DatabasePostgre.h index 7e541f84c73..9a2aeb84a07 100644 --- a/src/shared/Database/DatabasePostgre.h +++ b/src/shared/Database/DatabasePostgre.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/DatabaseSqlite.cpp b/src/shared/Database/DatabaseSqlite.cpp index 9de786bf739..a3fffd8aa4c 100644 --- a/src/shared/Database/DatabaseSqlite.cpp +++ b/src/shared/Database/DatabaseSqlite.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/DatabaseSqlite.h b/src/shared/Database/DatabaseSqlite.h index 325c3168acb..a9593989143 100644 --- a/src/shared/Database/DatabaseSqlite.h +++ b/src/shared/Database/DatabaseSqlite.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/Field.cpp b/src/shared/Database/Field.cpp index 20a88395b7e..18831e23687 100644 --- a/src/shared/Database/Field.cpp +++ b/src/shared/Database/Field.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/Field.h b/src/shared/Database/Field.h index 430e262c39e..a4514c963cd 100644 --- a/src/shared/Database/Field.h +++ b/src/shared/Database/Field.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/Makefile.am b/src/shared/Database/Makefile.am index 20cb2c87875..e5dce08653b 100644 --- a/src/shared/Database/Makefile.am +++ b/src/shared/Database/Makefile.am @@ -1,6 +1,6 @@ -# Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> # -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -9,19 +9,19 @@ # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Process this file with automake to produce Makefile.in ## Sub-directories to parse ## CPP flags for includes, defines, etc. -AM_CPPFLAGS = $(MYSQL_INCLUDES) $(POSTGRE_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite +AM_CPPFLAGS = $(TRINI_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite ## Build MaNGOS shared library and its parts as convenience library. # All libraries will be convenience libraries. Might be changed to shared @@ -29,36 +29,38 @@ AM_CPPFLAGS = $(MYSQL_INCLUDES) $(POSTGRE_INCLUDES) -I$(top_builddir)/src/shared noinst_LIBRARIES = libmangosdatabase.a libmangosdatabase_a_SOURCES = \ - DBCStores.cpp \ - DBCStores.h \ - DBCStructure.h \ - DBCfmt.cpp \ - Database.cpp \ - Database.h \ - DatabaseEnv.h \ - DatabaseImpl.h \ - DatabaseMysql.cpp \ - DatabasePostgre.cpp \ - DatabaseMysql.h \ - DatabasePostgre.h \ - DatabaseSqlite.cpp \ - DatabaseSqlite.h \ - Field.cpp \ - Field.h \ - MySQLDelayThread.h \ - PGSQLDelayThread.h \ - QueryResult.h \ - QueryResultMysql.cpp \ - QueryResultMysql.h \ - QueryResultPostgre.cpp \ - QueryResultPostgre.h \ - QueryResultSqlite.cpp \ - QueryResultSqlite.h \ - SQLStorage.cpp \ - SQLStorage.h \ - SqlDelayThread.cpp \ - SqlDelayThread.h \ - SqlOperations.cpp \ - SqlOperations.h \ - dbcfile.cpp \ - dbcfile.h + DBCStores.cpp \ + DBCStores.h \ + DBCStructure.h \ + DBCfmt.cpp \ + Database.cpp \ + Database.h \ + DatabaseEnv.h \ + DatabaseImpl.h \ + DatabaseMysql.cpp \ + DatabasePostgre.cpp \ + DatabaseMysql.h \ + DatabasePostgre.h \ + DatabaseSqlite.cpp \ + DatabaseSqlite.h \ + DBCEnums.h \ + Field.cpp \ + Field.h \ + MySQLDelayThread.h \ + PGSQLDelayThread.h \ + QueryResult.h \ + QueryResultMysql.cpp \ + QueryResultMysql.h \ + QueryResultPostgre.cpp \ + QueryResultPostgre.h \ + QueryResultSqlite.cpp \ + QueryResultSqlite.h \ + SQLStorage.cpp \ + SQLStorage.h \ + SQLStorageImpl.h \ + SqlDelayThread.cpp \ + SqlDelayThread.h \ + SqlOperations.cpp \ + SqlOperations.h \ + dbcfile.cpp \ + dbcfile.h diff --git a/src/shared/Database/MySQLDelayThread.h b/src/shared/Database/MySQLDelayThread.h index b01d88b6f72..5f3e66de722 100644 --- a/src/shared/Database/MySQLDelayThread.h +++ b/src/shared/Database/MySQLDelayThread.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/PGSQLDelayThread.h b/src/shared/Database/PGSQLDelayThread.h index 0525fb9f6d6..bd6a2bf962d 100644 --- a/src/shared/Database/PGSQLDelayThread.h +++ b/src/shared/Database/PGSQLDelayThread.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/QueryResult.h b/src/shared/Database/QueryResult.h index ab87fda59be..0fab7a3633b 100644 --- a/src/shared/Database/QueryResult.h +++ b/src/shared/Database/QueryResult.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/QueryResultMysql.cpp b/src/shared/Database/QueryResultMysql.cpp index 63808060b9f..8ae59b350d8 100644 --- a/src/shared/Database/QueryResultMysql.cpp +++ b/src/shared/Database/QueryResultMysql.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/QueryResultMysql.h b/src/shared/Database/QueryResultMysql.h index 79f5439ed06..39d2985ad77 100644 --- a/src/shared/Database/QueryResultMysql.h +++ b/src/shared/Database/QueryResultMysql.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/QueryResultPostgre.cpp b/src/shared/Database/QueryResultPostgre.cpp index 8ebe03ede64..e10905f0feb 100644 --- a/src/shared/Database/QueryResultPostgre.cpp +++ b/src/shared/Database/QueryResultPostgre.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/QueryResultPostgre.h b/src/shared/Database/QueryResultPostgre.h index ac7f31223ba..aa183ab4b96 100644 --- a/src/shared/Database/QueryResultPostgre.h +++ b/src/shared/Database/QueryResultPostgre.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/QueryResultSqlite.cpp b/src/shared/Database/QueryResultSqlite.cpp index 2bf64ed49ab..9a32e36bc84 100644 --- a/src/shared/Database/QueryResultSqlite.cpp +++ b/src/shared/Database/QueryResultSqlite.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/QueryResultSqlite.h b/src/shared/Database/QueryResultSqlite.h index 1416ac426cc..d3462977e49 100644 --- a/src/shared/Database/QueryResultSqlite.h +++ b/src/shared/Database/QueryResultSqlite.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp index cd1c7908e46..2f4f4534b3a 100644 --- a/src/shared/Database/SQLStorage.cpp +++ b/src/shared/Database/SQLStorage.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,20 +27,20 @@ extern DatabasePostgre WorldDatabase; extern DatabaseMysql WorldDatabase; #endif -const char CreatureInfosrcfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiis"; -const char CreatureInfodstfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiii"; +const char CreatureInfosrcfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiisiilliiis"; +const char CreatureInfodstfmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiisiilliiii"; const char CreatureDataAddonInfofmt[]="iiiiiiiis"; const char CreatureModelfmt[]="iffbi"; const char CreatureInfoAddonInfofmt[]="iiiiiiiis"; -const char EquipmentInfofmt[]="iiiiiiiiii"; +const char EquipmentInfofmt[]="iiii"; const char GameObjectInfosrcfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis"; const char GameObjectInfodstfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiii"; -const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifsiiiii"; -const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiii"; +const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiisiiii"; +const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiii"; const char PageTextfmt[]="isi"; const char SpellThreatfmt[]="ii"; -const char InstanceTemplatesrcfmt[]="iiiiiiffffs"; -const char InstanceTemplatedstfmt[]="iiiiiiffffi"; +const char InstanceTemplatesrcfmt[]="iiiiiiiffffs"; +const char InstanceTemplatedstfmt[]="iiiiiiiffffi"; SQLStorage sCreatureStorage(CreatureInfosrcfmt, CreatureInfodstfmt, "entry","creature_template"); SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon"); diff --git a/src/shared/Database/SQLStorage.h b/src/shared/Database/SQLStorage.h index 5a429d185cb..f2250410c26 100644 --- a/src/shared/Database/SQLStorage.h +++ b/src/shared/Database/SQLStorage.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/SQLStorageImpl.h b/src/shared/Database/SQLStorageImpl.h index 4f10c6eee05..b820d68619b 100644 --- a/src/shared/Database/SQLStorageImpl.h +++ b/src/shared/Database/SQLStorageImpl.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/SqlDelayThread.cpp b/src/shared/Database/SqlDelayThread.cpp index a265b48e622..a35090adb7e 100644 --- a/src/shared/Database/SqlDelayThread.cpp +++ b/src/shared/Database/SqlDelayThread.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/SqlDelayThread.h b/src/shared/Database/SqlDelayThread.h index 093c1c843d0..1fc35741fc5 100644 --- a/src/shared/Database/SqlDelayThread.h +++ b/src/shared/Database/SqlDelayThread.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,7 +42,7 @@ class SqlDelayThread : public ZThread::Runnable SqlDelayThread(Database* db); ///< Put sql statement to delay queue - inline bool Delay(SqlOperation* sql) { m_sqlQueue.add(sql); return true; } + bool Delay(SqlOperation* sql) { m_sqlQueue.add(sql); return true; } virtual void Stop(); ///< Stop event virtual void run(); ///< Main Thread loop diff --git a/src/shared/Database/SqlOperations.cpp b/src/shared/Database/SqlOperations.cpp index 1a81c4c96a1..233eed1e4cb 100644 --- a/src/shared/Database/SqlOperations.cpp +++ b/src/shared/Database/SqlOperations.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/SqlOperations.h b/src/shared/Database/SqlOperations.h index 0ebff9868d9..b7c84b5d6cf 100644 --- a/src/shared/Database/SqlOperations.h +++ b/src/shared/Database/SqlOperations.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/dbcfile.cpp b/src/shared/Database/dbcfile.cpp index 9f570e72496..f0b7e6e3c15 100644 --- a/src/shared/Database/dbcfile.cpp +++ b/src/shared/Database/dbcfile.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Database/dbcfile.h b/src/shared/Database/dbcfile.h index e0cef4dee5f..470322326aa 100644 --- a/src/shared/Database/dbcfile.h +++ b/src/shared/Database/dbcfile.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Errors.h b/src/shared/Errors.h index 0e8feb8424a..a521ae7f3f0 100644 --- a/src/shared/Errors.h +++ b/src/shared/Errors.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Log.cpp b/src/shared/Log.cpp index 9e910a4fcbf..2ed66ae3189 100644 --- a/src/shared/Log.cpp +++ b/src/shared/Log.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Log.h b/src/shared/Log.h index c4190264f3a..076d660be61 100644 --- a/src/shared/Log.h +++ b/src/shared/Log.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Makefile.am b/src/shared/Makefile.am index 3a86f148521..a5465f86c11 100644 --- a/src/shared/Makefile.am +++ b/src/shared/Makefile.am @@ -1,6 +1,6 @@ -# Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> # -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -18,96 +18,40 @@ ## Process this file with automake to produce Makefile.in -## TODO move vmaps in src dir instead of src/shared - ## Sub-directories to parse -SUBDIRS = vmap +SUBDIRS = Auth Config Database vmap + +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = $(TRINI_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../dep/include -I$(srcdir)/../framework -I$(srcdir)/../shared -I$(srcdir)/../../dep/include/g3dlite -DSYSCONFDIR=\"$(sysconfdir)/\" +## AM_CPPFLAGS += -I$(srcdir)/../game -I$(srcdir)/../realmd ## Build MaNGOS shared library and its parts as convenience library. # All libraries will be convenience libraries. Might be changed to shared # later. -noinst_LIBRARIES = libshared.a - -libshared_a_CPPFLAGS = \ -$(MYSQL_INCLUDES) \ -$(POSTGRE_INCLUDES) \ -$(TRINI_INCLUDES) \ --I$(top_srcdir)/dep/include \ --I$(top_srcdir)/src/framework +noinst_LIBRARIES = libmangosshared.a # libmangosshared library will later be reused by ... -libshared_a_SOURCES = \ -$(srcdir)/Base.cpp \ -$(srcdir)/Base.h \ -$(srcdir)/ByteBuffer.h \ -$(srcdir)/Common.cpp \ -$(srcdir)/Common.h \ -$(srcdir)/Errors.h \ -$(srcdir)/Log.cpp \ -$(srcdir)/Log.h \ -$(srcdir)/Mthread.cpp \ -$(srcdir)/Mthread.h \ -$(srcdir)/ProgressBar.cpp \ -$(srcdir)/ProgressBar.h \ -$(srcdir)/Timer.h \ -$(srcdir)/Util.cpp \ -$(srcdir)/Util.h \ -$(srcdir)/WorldPacket.h \ -$(srcdir)/SystemConfig.h \ -$(srcdir)../game/IRCConf.h \ -$(srcdir)/Auth/AuthCrypt.cpp \ -$(srcdir)/Auth/AuthCrypt.h \ -$(srcdir)/Auth/BigNumber.cpp \ -$(srcdir)/Auth/BigNumber.h \ -$(srcdir)/Auth/Hmac.cpp \ -$(srcdir)/Auth/Hmac.h \ -$(srcdir)/Auth/Sha1.cpp \ -$(srcdir)/Auth/Sha1.h \ -$(srcdir)/Auth/md5.c \ -$(srcdir)/Auth/md5.h \ -$(srcdir)/Config/dotconfpp/dotconfpp.cpp \ -$(srcdir)/Config/dotconfpp/dotconfpp.h \ -$(srcdir)/Config/dotconfpp/mempool.cpp \ -$(srcdir)/Config/dotconfpp/mempool.h \ -$(srcdir)/Config/Config.cpp \ -$(srcdir)/Config/Config.h \ -$(srcdir)/Config/ConfigEnv.h \ -$(srcdir)/Database/DBCStores.cpp \ -$(srcdir)/Database/DBCStores.h \ -$(srcdir)/Database/DBCStructure.h \ -$(srcdir)/Database/DBCfmt.cpp \ -$(srcdir)/Database/Database.cpp \ -$(srcdir)/Database/Database.h \ -$(srcdir)/Database/DatabaseEnv.h \ -$(srcdir)/Database/DatabaseImpl.h \ -$(srcdir)/Database/DatabaseMysql.cpp \ -$(srcdir)/Database/DatabasePostgre.cpp \ -$(srcdir)/Database/DatabaseMysql.h \ -$(srcdir)/Database/DatabasePostgre.h \ -$(srcdir)/Database/DatabaseSqlite.cpp \ -$(srcdir)/Database/DatabaseSqlite.h \ -$(srcdir)/Database/Field.cpp \ -$(srcdir)/Database/Field.h \ -$(srcdir)/Database/MySQLDelayThread.h \ -$(srcdir)/Database/PGSQLDelayThread.h \ -$(srcdir)/Database/QueryResult.h \ -$(srcdir)/Database/QueryResultMysql.cpp \ -$(srcdir)/Database/QueryResultMysql.h \ -$(srcdir)/Database/QueryResultPostgre.cpp \ -$(srcdir)/Database/QueryResultPostgre.h \ -$(srcdir)/Database/QueryResultSqlite.cpp \ -$(srcdir)/Database/QueryResultSqlite.h \ -$(srcdir)/Database/SQLStorage.cpp \ -$(srcdir)/Database/SQLStorage.h \ -$(srcdir)/Database/SqlDelayThread.cpp \ -$(srcdir)/Database/SqlDelayThread.h \ -$(srcdir)/Database/SqlOperations.cpp \ -$(srcdir)/Database/SqlOperations.h \ -$(srcdir)/Database/dbcfile.cpp \ -$(srcdir)/Database/dbcfile.h \ -$(srcdir)/revision.h - +libmangosshared_a_SOURCES = \ + Base.cpp \ + Base.h \ + ByteBuffer.h \ + Common.cpp \ + Common.h \ + Errors.h \ + Log.cpp \ + Log.h \ + MemoryLeaks.cpp \ + MemoryLeaks.h \ + ProgressBar.cpp \ + ProgressBar.h \ + Timer.h \ + Util.cpp \ + Util.h \ + WorldPacket.h \ + revision_nr.h \ + revision.h +# Get revision (git or svn) # Get HG revision REVISION_FILE = revision.h diff --git a/src/shared/MemoryLeaks.cpp b/src/shared/MemoryLeaks.cpp new file mode 100644 index 00000000000..ef7e36c3b57 --- /dev/null +++ b/src/shared/MemoryLeaks.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MemoryLeaks.h" +#include "Policies/SingletonImp.h" + +INSTANTIATE_SINGLETON_1( MemoryManager ) ; + +MemoryManager::MemoryManager( ) +{ + #if COMPILER == MICROSOFT + // standard leak check initialization + //_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + // uncomment to disable Visual Leak Detector from code + //VLDDisable(); + #endif +} diff --git a/src/shared/MemoryLeaks.h b/src/shared/MemoryLeaks.h new file mode 100644 index 00000000000..fcea1f557b1 --- /dev/null +++ b/src/shared/MemoryLeaks.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITYSERVER_MEMORY_H +#define TRINITYSERVER_MEMORY_H + +#include "Platform/CompilerDefs.h" + +#if COMPILER == COMPILER_MICROSOFT + +#ifndef _WIN64 +// Visual Leak Detector support enabled +//#include <vld/vld.h> +// standard Visual Studio leak check disabled, +//# define _CRTDBG_MAP_ALLOC +//# include <stdlib.h> +//# include <crtdbg.h> +#else +# define _CRTDBG_MAP_ALLOC +# include <stdlib.h> +# include <crtdbg.h> +#endif + +#endif + + +#include "Policies/Singleton.h" + +struct MemoryManager : public Trinity::Singleton < MemoryManager > +{ + MemoryManager(); +}; +#endif diff --git a/src/shared/PacketLog.cpp b/src/shared/PacketLog.cpp index 0ae6f198640..2fcd6c58b9b 100644 --- a/src/shared/PacketLog.cpp +++ b/src/shared/PacketLog.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/PacketLog.h b/src/shared/PacketLog.h index 3280d801261..b4313c48624 100644 --- a/src/shared/PacketLog.h +++ b/src/shared/PacketLog.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/ProgressBar.cpp b/src/shared/ProgressBar.cpp index 3cb09290485..0108dfec974 100644 --- a/src/shared/ProgressBar.cpp +++ b/src/shared/ProgressBar.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/ProgressBar.h b/src/shared/ProgressBar.h index 77f1e4c43ec..8c551ed65dc 100644 --- a/src/shared/ProgressBar.h +++ b/src/shared/ProgressBar.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/ServiceWin32.cpp b/src/shared/ServiceWin32.cpp index 2a152513977..878656b1d91 100644 --- a/src/shared/ServiceWin32.cpp +++ b/src/shared/ServiceWin32.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/shared/ServiceWin32.h b/src/shared/ServiceWin32.h index fdc9d7d4e9e..762502ccaa7 100644 --- a/src/shared/ServiceWin32.h +++ b/src/shared/ServiceWin32.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/src/shared/SystemConfig.h b/src/shared/SystemConfig.h index 9e7fe3e3045..7d0143085b4 100644 --- a/src/shared/SystemConfig.h +++ b/src/shared/SystemConfig.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * * This program is free software; you can redistribute it and/or modify @@ -28,7 +28,7 @@ #include "revision.h" -#define _PACKAGENAME "TrinityCore " +#define _PACKAGENAME "TC&MaNGOS " #define _CODENAME "YUME" #if TRINITY_ENDIAN == TRINITY_BIGENDIAN diff --git a/src/shared/SystemConfig.h.in b/src/shared/SystemConfig.h.in new file mode 100644 index 00000000000..6eff490b144 --- /dev/null +++ b/src/shared/SystemConfig.h.in @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRINITY_SYSTEMCONFIG_H +#define TRINITY_SYSTEMCONFIG_H + +#ifndef _PACKAGENAME +#define _PACKAGENAME "TC&Mangos " +#endif + +#include "Platform/Define.h" +#include "revision.h" //-----here u are ------ _REVISION is the magic key + +#ifndef _VERSION +#if PLATFORM == PLATFORM_WINDOWS +# define _VERSION(REVD,REVT,REVN,REVH) "0.13.0-DEV" " (" REVD " " REVT " Revision " REVN " - " REVH ")" +#else +# define _VERSION(REVD,REVT,REVN,REVH) "@VERSION@" " (" REVD " " REVT " Revision " REVN " - " REVH ")" +#endif +#endif + +// Format is YYYYMMDDRR where RR is the change in the conf file +// for that day. +#ifndef _MANGOSDCONFVERSION +# define _MANGOSDCONFVERSION 2008022901 +#endif +#ifndef _REALMDCONFVERSION +# define _REALMDCONFVERSION 2007062001 +#endif + +#if MANGOS_ENDIAN == MANGOS_BIGENDIAN +# define _ENDIAN_STRING "big-endian" +#else +# define _ENDIAN_STRING "little-endian" +#endif + +// The path to config files +#ifndef SYSCONFDIR +# define SYSCONFDIR "" +#endif + +#if PLATFORM == PLATFORM_WINDOWS +# ifdef _WIN64 +# define _ENDIAN_PLATFORM "Win64 (" _ENDIAN_STRING ")" +# else +# define _ENDIAN_PLATFORM "Win32 (" _ENDIAN_STRING ")" +# endif +# define _MANGOSD_CONFIG SYSCONFDIR"mangosd.conf" +# define _REALMD_CONFIG SYSCONFDIR"realmd.conf" +#else +# define _ENDIAN_PLATFORM "Unix (" _ENDIAN_STRING ")" +# define _MANGOSD_CONFIG SYSCONFDIR"mangosd.conf" +# define _REALMD_CONFIG SYSCONFDIR"realmd.conf" +#endif + + +#define DEFAULT_PLAYER_LIMIT 100 +#define DEFAULT_WORLDSERVER_PORT 8085 //8129 +#define DEFAULT_REALMSERVER_PORT 3724 +#define DEFAULT_SOCKET_SELECT_TIME 10000 +#endif diff --git a/src/shared/Timer.h b/src/shared/Timer.h index 848a8cfac4f..30f5966afce 100644 --- a/src/shared/Timer.h +++ b/src/shared/Timer.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/Util.cpp b/src/shared/Util.cpp index 72b35319298..0d3010c5f04 100644 --- a/src/shared/Util.cpp +++ b/src/shared/Util.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,27 +36,27 @@ static MTRandTSS mtRand; int32 irand (int32 min, int32 max) { - return int32 (mtRand.get ().randInt (max - min)) + min; + return int32 (mtRand.get ().randInt (max - min)) + min; } uint32 urand (uint32 min, uint32 max) { - return mtRand.get ().randInt (max - min) + min; + return mtRand.get ().randInt (max - min) + min; } int32 rand32 () { - return mtRand.get ().randInt (); + return mtRand.get ().randInt (); } double rand_norm(void) { - return mtRand.get ().randExc (); + return mtRand.get ().randExc (); } double rand_chance (void) { - return mtRand.get ().randExc (100.0); + return mtRand.get ().randExc (100.0); } Tokens StrSplit(const std::string &src, const std::string &sep) diff --git a/src/shared/Util.h b/src/shared/Util.h index 4b91a8ede4c..adfbdad620a 100644 --- a/src/shared/Util.h +++ b/src/shared/Util.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -287,20 +287,20 @@ bool consoleToUtf8(const std::string& conStr,std::string& utf8str); bool Utf8FitTo(const std::string& str, std::wstring search); #if PLATFORM == PLATFORM_WINDOWS -#define UTF8PRINTF(OUT,FRM,RESERR) \ -{ \ - char temp_buf[6000]; \ - va_list ap; \ - va_start(ap, FRM); \ - size_t temp_len = vsnprintf(temp_buf,6000,FRM,ap); \ - va_end(ap); \ - \ - wchar_t wtemp_buf[6000]; \ - size_t wtemp_len = 6000-1; \ +#define UTF8PRINTF(OUT,FRM,RESERR) \ +{ \ + char temp_buf[32*1024]; \ + va_list ap; \ + va_start(ap, FRM); \ + size_t temp_len = vsnprintf(temp_buf,32*1024,FRM,ap); \ + va_end(ap); \ + \ + wchar_t wtemp_buf[32*1024]; \ + size_t wtemp_len = 32*1024-1; \ if(!Utf8toWStr(temp_buf,temp_len,wtemp_buf,wtemp_len)) \ - return RESERR; \ + return RESERR; \ CharToOemBuffW(&wtemp_buf[0],&temp_buf[0],wtemp_len+1);\ - fprintf(OUT,temp_buf); \ + fprintf(OUT,temp_buf); \ } #else #define UTF8PRINTF(OUT,FRM,RESERR) \ @@ -316,3 +316,232 @@ bool IsIPAddress(char const* ipaddress); uint32 CreatePIDFile(const std::string& filename); #endif + +//handler for operations on large flags +#ifndef _FLAG96 +#define _FLAG96 + +class flag96 +{ +private: + uint32 part[3]; +public: + flag96(uint32 p1=0,uint32 p2=0,uint32 p3=0) + { + part[0]=p1; + part[1]=p2; + part[2]=p3; + } + + inline bool IsEqual(uint32 p1=0, uint32 p2=0, uint32 p3=0) const + { + return ( + part[0]==p1 && + part[1]==p2 && + part[2]==p3); + }; + + inline bool HasFlag(uint32 p1=0, uint32 p2=0, uint32 p3=0) const + { + return ( + part[0]&p1 || + part[1]&p2 || + part[2]&p3); + }; + + inline void Set(uint32 p1=0, uint32 p2=0, uint32 p3=0) + { + part[0]=p1; + part[1]=p2; + part[2]=p3; + }; + + template<class type> + inline bool operator < (type & right) + { + for (uint8 i=3;i>0;i--) + { + if (part[i-1]<right.part[i-1]) + return 1; + else if (part[i-1]>right.part[i-1]) + return 0; + } + return 0; + }; + + template<class type> + inline bool operator < (type & right) const + { + for (uint8 i=3;i>0;i--) + { + if (part[i-1]<right.part[i-1]) + return 1; + else if (part[i-1]>right.part[i-1]) + return 0; + } + return 0; + }; + + template<class type> + inline bool operator != (type & right) + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return true; + return false; + } + + template<class type> + inline bool operator != (type & right) const + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return true; + return false; + }; + + template<class type> + inline bool operator == (type & right) + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return false; + return true; + }; + + template<class type> + inline bool operator == (type & right) const + { + if (part[0]!=right.part[0] + || part[1]!=right.part[1] + || part[2]!=right.part[2]) + return false; + return true; + }; + + template<class type> + inline void operator = (type & right) + { + part[0]=right.part[0]; + part[1]=right.part[1]; + part[2]=right.part[2]; + }; + + template<class type> + inline flag96 operator & (type & right) + { + flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]); + return + ret; + }; + template<class type> + inline flag96 operator & (type & right) const + { + flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]); + return + ret; + }; + + template<class type> + inline void operator &= (type & right) + { + *this=*this & right; + }; + + template<class type> + inline flag96 operator | (type & right) + { + flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]); + return + ret; + }; + + template<class type> + inline flag96 operator | (type & right) const + { + flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]); + return + ret; + }; + + template<class type> + inline void operator |= (type & right) + { + *this=*this | right; + }; + + inline void operator ~ () + { + part[2]=~part[2]; + part[1]=~part[1]; + part[0]=~part[0]; + }; + + template<class type> + inline flag96 operator ^ (type & right) + { + flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]); + return + ret; + }; + + template<class type> + inline flag96 operator ^ (type & right) const + { + flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]); + return + ret; + }; + + template<class type> + inline void operator ^= (type & right) + { + *this=*this^right; + }; + + inline operator bool() const + { + return( + part[0] != 0 || + part[1] != 0 || + part[2] != 0); + }; + + inline operator bool() + { + return( + part[0] != 0 || + part[1] != 0 || + part[2] != 0); + }; + + inline bool operator ! () const + { + return( + part[0] == 0 && + part[1] == 0 && + part[2] == 0); + }; + + inline bool operator ! () + { + return( + part[0] == 0 && + part[1] == 0 && + part[2] == 0); + }; + + inline uint32 & operator[](uint8 el) + { + return (part[el]); + }; + + inline const uint32 & operator[](uint8 el) const + { + return (part[el]); + }; +}; +#endif diff --git a/src/shared/WorldPacket.h b/src/shared/WorldPacket.h index ee17047a9ef..4d30533d2f1 100644 --- a/src/shared/WorldPacket.h +++ b/src/shared/WorldPacket.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h new file mode 100644 index 00000000000..048435dc33b --- /dev/null +++ b/src/shared/revision_nr.h @@ -0,0 +1,4 @@ +#ifndef __REVISION_NR_H__ +#define __REVISION_NR_H__ + #define REVISION_NR "7265" +#endif // __REVISION_NR_H__ diff --git a/src/shared/vmap/BaseModel.cpp b/src/shared/vmap/BaseModel.cpp index 1b7ad34d413..bce9c718acd 100644 --- a/src/shared/vmap/BaseModel.cpp +++ b/src/shared/vmap/BaseModel.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/BaseModel.h b/src/shared/vmap/BaseModel.h index 1601f367de7..42e277634ba 100644 --- a/src/shared/vmap/BaseModel.h +++ b/src/shared/vmap/BaseModel.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/CoordModelMapping.cpp b/src/shared/vmap/CoordModelMapping.cpp index 7c7c801d690..9c7cbe58a6b 100644 --- a/src/shared/vmap/CoordModelMapping.cpp +++ b/src/shared/vmap/CoordModelMapping.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/CoordModelMapping.h b/src/shared/vmap/CoordModelMapping.h index 34f1917f5b3..10392ca7eaf 100644 --- a/src/shared/vmap/CoordModelMapping.h +++ b/src/shared/vmap/CoordModelMapping.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/DebugCmdLogger.cpp b/src/shared/vmap/DebugCmdLogger.cpp index 5e26b7ade8f..26846fa5783 100644 --- a/src/shared/vmap/DebugCmdLogger.cpp +++ b/src/shared/vmap/DebugCmdLogger.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/DebugCmdLogger.h b/src/shared/vmap/DebugCmdLogger.h index aa0df4d1e5c..f0e35d377bf 100644 --- a/src/shared/vmap/DebugCmdLogger.h +++ b/src/shared/vmap/DebugCmdLogger.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/IVMapManager.h b/src/shared/vmap/IVMapManager.h index 60159ed8bea..49f639b845e 100644 --- a/src/shared/vmap/IVMapManager.h +++ b/src/shared/vmap/IVMapManager.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/Makefile.am b/src/shared/vmap/Makefile.am index 80b297f8def..3829117f2a9 100644 --- a/src/shared/vmap/Makefile.am +++ b/src/shared/vmap/Makefile.am @@ -1,6 +1,6 @@ -# Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> # -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +# Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -9,50 +9,50 @@ # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ## Process this file with automake to produce Makefile.in -noinst_LIBRARIES = libvmaps.a +## Sub-directories to parse -## Preprocessor flags -libvmaps_a_CPPFLAGS = \ -$(TRINI_INCLUDES) \ --I$(top_srcdir)/dep/include \ --I$(top_srcdir)/dep/include/g3dlite - -libvmaps_a_SOURCES = \ -$(srcdir)/AABSPTree.h \ -$(srcdir)/BaseModel.cpp \ -$(srcdir)/BaseModel.h \ -$(srcdir)/CoordModelMapping.cpp \ -$(srcdir)/CoordModelMapping.h \ -$(srcdir)/DebugCmdLogger.cpp \ -$(srcdir)/DebugCmdLogger.h \ -$(srcdir)/IVMapManager.h \ -$(srcdir)/ManagedModelContainer.cpp \ -$(srcdir)/ManagedModelContainer.h \ -$(srcdir)/ModelContainer.cpp \ -$(srcdir)/ModelContainer.h \ -$(srcdir)/NodeValueAccess.h \ -$(srcdir)/ShortBox.h \ -$(srcdir)/ShortVector.h \ -$(srcdir)/SubModel.cpp \ -$(srcdir)/SubModel.h \ -$(srcdir)/TileAssembler.cpp \ -$(srcdir)/TileAssembler.h \ -$(srcdir)/TreeNode.cpp \ -$(srcdir)/TreeNode.h \ -$(srcdir)/VMapDefinitions.h \ -$(srcdir)/VMapFactory.cpp \ -$(srcdir)/VMapFactory.h \ -$(srcdir)/VMapManager.cpp \ -$(srcdir)/VMapManager.h \ -$(srcdir)/VMapTools.h +## CPP flags for includes, defines, etc. +AM_CPPFLAGS = $(TRINI_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite +## Build MaNGOS shared library and its parts as convenience library. +# All libraries will be convenience libraries. Might be changed to shared +# later. +noinst_LIBRARIES = libmangosvmaps.a +libmangosvmaps_a_SOURCES = \ + AABSPTree.h \ + BaseModel.cpp \ + BaseModel.h \ + CoordModelMapping.cpp \ + CoordModelMapping.h \ + DebugCmdLogger.cpp \ + DebugCmdLogger.h \ + IVMapManager.h \ + ManagedModelContainer.cpp \ + ManagedModelContainer.h \ + ModelContainer.cpp \ + ModelContainer.h \ + NodeValueAccess.h \ + ShortBox.h \ + ShortVector.h \ + SubModel.cpp \ + SubModel.h \ + TileAssembler.cpp \ + TileAssembler.h \ + TreeNode.cpp \ + TreeNode.h \ + VMapDefinitions.h \ + VMapFactory.cpp \ + VMapFactory.h \ + VMapManager.cpp \ + VMapManager.h \ + VMapTools.h diff --git a/src/shared/vmap/ManagedModelContainer.cpp b/src/shared/vmap/ManagedModelContainer.cpp index 08c58a60c8f..34800b3b5f7 100644 --- a/src/shared/vmap/ManagedModelContainer.cpp +++ b/src/shared/vmap/ManagedModelContainer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/ManagedModelContainer.h b/src/shared/vmap/ManagedModelContainer.h index b193ef9d57f..5aa6bfdf1c3 100644 --- a/src/shared/vmap/ManagedModelContainer.h +++ b/src/shared/vmap/ManagedModelContainer.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/ModelContainer.cpp b/src/shared/vmap/ModelContainer.cpp index 4d2dc2aac78..a4bc5b8aa17 100644 --- a/src/shared/vmap/ModelContainer.cpp +++ b/src/shared/vmap/ModelContainer.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/ModelContainer.h b/src/shared/vmap/ModelContainer.h index 98b4c9ddcf3..f66b11658d6 100644 --- a/src/shared/vmap/ModelContainer.h +++ b/src/shared/vmap/ModelContainer.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/NodeValueAccess.h b/src/shared/vmap/NodeValueAccess.h index b8ec54e90be..70bd0eeefae 100644 --- a/src/shared/vmap/NodeValueAccess.h +++ b/src/shared/vmap/NodeValueAccess.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/ShortBox.h b/src/shared/vmap/ShortBox.h index 9c5472f4c3a..059e59f47e6 100644 --- a/src/shared/vmap/ShortBox.h +++ b/src/shared/vmap/ShortBox.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/ShortVector.h b/src/shared/vmap/ShortVector.h index 8c4aec8a0b4..d02e6b4081e 100644 --- a/src/shared/vmap/ShortVector.h +++ b/src/shared/vmap/ShortVector.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/SubModel.cpp b/src/shared/vmap/SubModel.cpp index 3d1c0e29ff6..ed586ce6b52 100644 --- a/src/shared/vmap/SubModel.cpp +++ b/src/shared/vmap/SubModel.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/SubModel.h b/src/shared/vmap/SubModel.h index bc8239b1568..5a0b0d38be7 100644 --- a/src/shared/vmap/SubModel.h +++ b/src/shared/vmap/SubModel.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/TileAssembler.cpp b/src/shared/vmap/TileAssembler.cpp index fd83a318f65..e57836a6f9e 100644 --- a/src/shared/vmap/TileAssembler.cpp +++ b/src/shared/vmap/TileAssembler.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -75,12 +75,12 @@ namespace VMAP addWorldAreaMapId(0); //Azeroth addWorldAreaMapId(1); //Kalimdor addWorldAreaMapId(530); //Expansion01 + addWorldAreaMapId(571); //Expansion02 } //================================================================= std::string getModNameFromModPosName(const std::string& pModPosName) { - size_t spos = pModPosName.find_first_of('#'); std::string modelFileName = pModPosName.substr(0,spos); return(modelFileName); @@ -142,7 +142,6 @@ namespace VMAP //================================================================= bool TileAssembler::convertWorld() { - #ifdef _ASSEMBLER_DEBUG # ifdef _DEBUG ::g_df = fopen("../TileAssembler_debug.txt", "wb"); diff --git a/src/shared/vmap/TileAssembler.h b/src/shared/vmap/TileAssembler.h index 3f0f9468172..cdfd6e1311d 100644 --- a/src/shared/vmap/TileAssembler.h +++ b/src/shared/vmap/TileAssembler.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/TreeNode.cpp b/src/shared/vmap/TreeNode.cpp index af7fe224fe5..1c0cff7d4b3 100644 --- a/src/shared/vmap/TreeNode.cpp +++ b/src/shared/vmap/TreeNode.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/TreeNode.h b/src/shared/vmap/TreeNode.h index 8f3fbd7a71a..d30b470b4b3 100644 --- a/src/shared/vmap/TreeNode.h +++ b/src/shared/vmap/TreeNode.h @@ -1,7 +1,7 @@ /* -* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * -* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/VMapDefinitions.h b/src/shared/vmap/VMapDefinitions.h index c3498ea9260..35c672bd82e 100644 --- a/src/shared/vmap/VMapDefinitions.h +++ b/src/shared/vmap/VMapDefinitions.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/VMapFactory.cpp b/src/shared/vmap/VMapFactory.cpp index 4c349cdaa62..f0a78ba4f1c 100644 --- a/src/shared/vmap/VMapFactory.cpp +++ b/src/shared/vmap/VMapFactory.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/VMapFactory.h b/src/shared/vmap/VMapFactory.h index a8784a37219..738a8a7f4e0 100644 --- a/src/shared/vmap/VMapFactory.h +++ b/src/shared/vmap/VMapFactory.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/VMapManager.cpp b/src/shared/vmap/VMapManager.cpp index cf2bc080865..9cf35b2655d 100644 --- a/src/shared/vmap/VMapManager.cpp +++ b/src/shared/vmap/VMapManager.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/VMapManager.h b/src/shared/vmap/VMapManager.h index 5b4064915e4..02e0ec3e179 100644 --- a/src/shared/vmap/VMapManager.h +++ b/src/shared/vmap/VMapManager.h @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/shared/vmap/VMapTools.h b/src/shared/vmap/VMapTools.h index 49a28d5272d..5253392f867 100644 --- a/src/shared/vmap/VMapTools.h +++ b/src/shared/vmap/VMapTools.h @@ -1,7 +1,7 @@ /* -* Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> +* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * -* Copyright (C) 2008 Trinity <http://www.trinitycore.org/> +* Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am index 333cba05861..81040a49592 100644 --- a/src/tools/Makefile.am +++ b/src/tools/Makefile.am @@ -1,2 +1,23 @@ +# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + ## Sub-directories to parse SUBDIRS = genrevision + +## Additional files to include when running 'make dist' +# Nothing yet. diff --git a/src/tools/genrevision/Makefile.am b/src/tools/genrevision/Makefile.am index faf5451f652..3f60ac14ab2 100644 --- a/src/tools/genrevision/Makefile.am +++ b/src/tools/genrevision/Makefile.am @@ -1,17 +1,35 @@ +# Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## Process this file with automake to produce Makefile.in + ## CPP flags for includes, defines, etc. AM_CPPFLAGS = -I$(srcdir) ## Build world list daemon as standalone program bin_PROGRAMS = genrevision genrevision_SOURCES = \ - genrevision.cpp + genrevision.cpp ## Link world daemon against the shared library -genrevision_LDADD = +genrevision_LDADD = genrevision_LDFLAGS = -L$(libdir) ## Additional files to include when running 'make dist' # Include world daemon configuration -#EXTRA_DIST = +#EXTRA_DIST = ## Additional files to install diff --git a/src/tools/genrevision/genrevision.cpp b/src/tools/genrevision/genrevision.cpp index 99c407c33d9..83cf4da7c62 100644 --- a/src/tools/genrevision/genrevision.cpp +++ b/src/tools/genrevision/genrevision.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/trinitycore/CliRunnable.cpp b/src/trinitycore/CliRunnable.cpp index 267a8d41a27..a0609309298 100644 --- a/src/trinitycore/CliRunnable.cpp +++ b/src/trinitycore/CliRunnable.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/trinitycore/Main.cpp b/src/trinitycore/Main.cpp index d24ae02d426..df9d9185deb 100644 --- a/src/trinitycore/Main.cpp +++ b/src/trinitycore/Main.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/trinitycore/Makefile.am b/src/trinitycore/Makefile.am deleted file mode 100644 index ad1b78d9033..00000000000 --- a/src/trinitycore/Makefile.am +++ /dev/null @@ -1,85 +0,0 @@ -# Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> -# -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -## Process this file with automake to produce Makefile.in - -## Build world list daemon as standalone program -bin_PROGRAMS = trinity-core - -## Preprocessor flags -trinity_core_CPPFLAGS = \ -$(MYSQL_INCLUDES) \ -$(POSTGRE_INCLUDES) \ -$(TRINI_INCLUDES) \ --I$(top_srcdir)/dep/include \ --I$(top_srcdir)/src/shared \ --I$(top_srcdir)/src/framework \ --I$(top_srcdir)/src/game \ --D_TRINITY_CORE_CONFIG='"$(sysconfdir)/trinitycore.conf"' - -## Sources -trinity_core_SOURCES = \ -$(srcdir)/CliRunnable.cpp \ -$(srcdir)/CliRunnable.h \ -$(srcdir)/Main.cpp \ -$(srcdir)/Master.cpp \ -$(srcdir)/Master.h \ -$(srcdir)/RASocket.cpp \ -$(srcdir)/RASocket.h \ -$(srcdir)/WorldRunnable.cpp \ -$(srcdir)/WorldRunnable.h - -## Convenience libs to add -trinity_core_LDADD = \ -$(top_builddir)/src/game/libgame.a \ -$(top_builddir)/src/shared/libshared.a \ -$(top_builddir)/src/shared/vmap/libvmaps.a \ -$(top_builddir)/src/framework/libmangosframework.a \ -$(top_builddir)/dep/src/sockets/libmangossockets.a \ -$(top_builddir)/dep/src/zthread/libZThread.la \ -$(top_builddir)/dep/src/g3dlite/libg3dlite.a - -if USE_TSCRIPTS -trinity_core_LDADD += $(top_builddir)/src/bindings/scripts/libtrinityscript.la -else -trinity_core_LDADD += $(top_builddir)/src/bindings/interface/libtrinityscript.la -endif - -## Linker flags -trinity_core_LDFLAGS = $(MYSQL_LIBS) $(POSTGRE_LIBS) $(ZLIB) $(COMPATLIB) $(SSLLIB) $(TRINI_LIBS) -export-dynamic - -## Additional files to install -sysconf_DATA = \ - trinitycore.conf.dist - -EXTRA_DIST = \ - trinitycore.conf.dist - -## Prevend overwrite of the config file, if its already installed -install-data-hook: - @list='$(sysconf_DATA)'; for p in $$list; do \ - dest=`echo $$p | sed -e s/.dist//`; \ - if test -f $(DESTDIR)$(sysconfdir)/$$dest; then \ - echo "$@ will not overwrite existing $(DESTDIR)$(sysconfdir)/$$dest"; \ - else \ - echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$dest"; \ - $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$dest; \ - fi; \ - done - - diff --git a/src/trinitycore/Master.cpp b/src/trinitycore/Master.cpp index 66c1c17664e..8eeda54ab83 100644 --- a/src/trinitycore/Master.cpp +++ b/src/trinitycore/Master.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/trinitycore/RASocket.cpp b/src/trinitycore/RASocket.cpp index cfc50d95f89..a48928d5a23 100644 --- a/src/trinitycore/RASocket.cpp +++ b/src/trinitycore/RASocket.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/trinitycore/WorldRunnable.cpp b/src/trinitycore/WorldRunnable.cpp index e4f1a79a6e8..ec4c25a6cf6 100644 --- a/src/trinitycore/WorldRunnable.cpp +++ b/src/trinitycore/WorldRunnable.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/trinityrealm/AuthSocket.cpp b/src/trinityrealm/AuthSocket.cpp index 6f8363a9724..c5c81593737 100644 --- a/src/trinityrealm/AuthSocket.cpp +++ b/src/trinityrealm/AuthSocket.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/trinityrealm/Main.cpp b/src/trinityrealm/Main.cpp index 274aabf0717..95829ee96ca 100644 --- a/src/trinityrealm/Main.cpp +++ b/src/trinityrealm/Main.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/trinityrealm/Makefile.am b/src/trinityrealm/Makefile.am deleted file mode 100644 index 9baeed6c2b1..00000000000 --- a/src/trinityrealm/Makefile.am +++ /dev/null @@ -1,72 +0,0 @@ -# Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> -# -# Copyright (C) 2008 Trinity <http://www.trinitycore.org/> -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -## Process this file with automake to produce Makefile.in - -## Build realm list daemon as standalone program -bin_PROGRAMS = trinity-realm - -## Preprocessor flags -trinity_realm_CPPFLAGS = \ -$(MYSQL_INCLUDES) \ -$(POSTGRE_INCLUDES) \ -$(TRINI_INCLUDES) \ --I$(top_srcdir)/dep/include \ --I$(top_srcdir)/src/framework \ --I$(top_srcdir)/src/shared \ --D_TRINITY_REALM_CONFIG='"$(sysconfdir)/trinityrealm.conf"' - -## Sources -trinity_realm_SOURCES = \ -$(srcdir)/AuthCodes.h \ -$(srcdir)/AuthSocket.cpp \ -$(srcdir)/AuthSocket.h \ -$(srcdir)/Main.cpp \ -$(srcdir)/RealmList.cpp \ -$(srcdir)/RealmList.h - -## Convenience libs to add -trinity_realm_LDADD = \ -$(top_builddir)/src/shared/libshared.a \ -$(top_builddir)/src/framework/libmangosframework.a \ -$(top_builddir)/dep/src/sockets/libmangossockets.a \ -$(top_builddir)/dep/src/zthread/libZThread.la - -## Linker flags -trinity_realm_LDFLAGS = $(MYSQL_LIBS) $(POSTGRE_LIBS) $(ZLIB) $(COMPATLIB) $(SSLLIB) $(TRINI_LIBS) - -## Additional files to install -sysconf_DATA = \ - trinityrealm.conf.dist - -## Prevend overwrite of the config file, if its already installed -install-data-hook: - @list='$(sysconf_DATA)'; for p in $$list; do \ - dest=`echo $$p | sed -e s/.dist//`; \ - if test -f $(DESTDIR)$(sysconfdir)/$$dest; then \ - echo "$@ will not overwrite existing $(DESTDIR)$(sysconfdir)/$$dest"; \ - else \ - echo " $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$dest"; \ - $(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(sysconfdir)/$$dest; \ - fi; \ - done - -## Additional files to include when running 'make dist' -EXTRA_DIST = trinityrealm.conf.dist - - diff --git a/src/trinityrealm/RealmList.cpp b/src/trinityrealm/RealmList.cpp index 558d6c12610..6a3d6b47e0f 100644 --- a/src/trinityrealm/RealmList.cpp +++ b/src/trinityrealm/RealmList.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by |