From 612b22dc87fc1ff27e1a2f0e70bad7ec56671ff6 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 26 Oct 2008 10:08:43 +0300 Subject: [PATCH 001/256] Added calendar placeholder --- src/game/Calendar.cpp | 17 ++++++ src/game/Calendar.h | 26 +++++++++ src/game/CalendarHandler.cpp | 108 +++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+) create mode 100644 src/game/Calendar.cpp create mode 100644 src/game/Calendar.h create mode 100644 src/game/CalendarHandler.cpp diff --git a/src/game/Calendar.cpp b/src/game/Calendar.cpp new file mode 100644 index 000000000..cebf7252e --- /dev/null +++ b/src/game/Calendar.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This 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 000000000..94e4ff103 --- /dev/null +++ b/src/game/Calendar.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This 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 000000000..e548a6696 --- /dev/null +++ b/src/game/CalendarHandler.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This 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" + +void WorldSession::HandleCalendarGetCalendar(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_GET_CALENDAR"); + recv_data.hexlike(); +} + +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(); +} From bfaf5660f8144d4cd3eca59a86ab26b68ce235e5 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 26 Oct 2008 10:10:32 +0300 Subject: [PATCH 002/256] Updated project files --- win/VC71/game.vcproj | 9 +++++++++ win/VC80/game.vcproj | 12 ++++++++++++ win/VC90/game.vcproj | 12 ++++++++++++ 3 files changed, 33 insertions(+) diff --git a/win/VC71/game.vcproj b/win/VC71/game.vcproj index aa6ae724e..b59d8a262 100644 --- a/win/VC71/game.vcproj +++ b/win/VC71/game.vcproj @@ -210,6 +210,9 @@ + + @@ -480,6 +483,12 @@ + + + + diff --git a/win/VC80/game.vcproj b/win/VC80/game.vcproj index e3ed6b512..67b4ec56d 100644 --- a/win/VC80/game.vcproj +++ b/win/VC80/game.vcproj @@ -454,6 +454,10 @@ RelativePath="..\..\src\game\BattleGroundWS.h" > + + @@ -814,6 +818,14 @@ RelativePath="..\..\src\game\Bag.h" > + + + + diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj index 8d914b3a7..09e58cfad 100644 --- a/win/VC90/game.vcproj +++ b/win/VC90/game.vcproj @@ -455,6 +455,10 @@ RelativePath="..\..\src\game\BattleGroundWS.h" > + + @@ -815,6 +819,14 @@ RelativePath="..\..\src\game\Bag.h" > + + + + From 06bf7fff6504c77535d570e6494b366800ed9715 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 26 Oct 2008 10:11:10 +0300 Subject: [PATCH 003/256] Added SQL updates --- sql/wotlk_updates/1_mangos_creature_equip_template.sql | 10 ++++++++++ sql/wotlk_updates/2_character_character_pet.sql | 5 +++++ sql/wotlk_updates/3_mangos_item_template.sql | 5 +++++ 3 files changed, 20 insertions(+) create mode 100644 sql/wotlk_updates/1_mangos_creature_equip_template.sql create mode 100644 sql/wotlk_updates/2_character_character_pet.sql create mode 100644 sql/wotlk_updates/3_mangos_item_template.sql diff --git a/sql/wotlk_updates/1_mangos_creature_equip_template.sql b/sql/wotlk_updates/1_mangos_creature_equip_template.sql new file mode 100644 index 000000000..f844f50af --- /dev/null +++ b/sql/wotlk_updates/1_mangos_creature_equip_template.sql @@ -0,0 +1,10 @@ +alter table `creature_equip_template` + drop column `equipinfo1`, + drop column `equipinfo2`, + drop column `equipinfo3`, + drop column `equipslot1`, + drop column `equipslot2`, + drop column `equipslot3`, + change `equipmodel1` `equipentry1` mediumint(8) UNSIGNED default '0' NOT NULL, + change `equipmodel2` `equipentry2` mediumint(8) UNSIGNED default '0' NOT NULL, + change `equipmodel3` `equipentry3` mediumint(8) UNSIGNED default '0' NOT NULL; diff --git a/sql/wotlk_updates/2_character_character_pet.sql b/sql/wotlk_updates/2_character_character_pet.sql new file mode 100644 index 000000000..98c0f6aad --- /dev/null +++ b/sql/wotlk_updates/2_character_character_pet.sql @@ -0,0 +1,5 @@ +alter table `character_pet` + drop column `trainpoint`, + drop column `loyaltypoints`, + drop column `loyalty`, + add `talentpoints` int(11) UNSIGNED default '0' NOT NULL after `Reactstate`; diff --git a/sql/wotlk_updates/3_mangos_item_template.sql b/sql/wotlk_updates/3_mangos_item_template.sql new file mode 100644 index 000000000..09de10c3e --- /dev/null +++ b/sql/wotlk_updates/3_mangos_item_template.sql @@ -0,0 +1,5 @@ +alter table `item_template` + add column `ScalingStatDistribution` smallint(6) DEFAULT '0' NOT NULL after `stat_value10`, + add column `ScalingStatValue` smallint(6) DEFAULT '0' NOT NULL after `ScalingStatDistribution`, + add column `ItemLimitCategory` smallint(6) DEFAULT '0' NOT NULL after `ArmorDamageModifier`, + change `Duration` `Duration` int(11) NOT NULL default '0' COMMENT 'Duration in seconds. Negative value means realtime, postive value ingame time' after ArmorDamageModifier; From 9ad0318c0984d66fb4c208f3fa65de8f18a605f6 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 26 Oct 2008 10:12:09 +0300 Subject: [PATCH 004/256] Disabled vld --- src/shared/MemoryLeaks.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/MemoryLeaks.h b/src/shared/MemoryLeaks.h index 2cd4c181a..fceb9d6f4 100644 --- a/src/shared/MemoryLeaks.h +++ b/src/shared/MemoryLeaks.h @@ -25,7 +25,7 @@ #ifndef _WIN64 // Visual Leak Detector support enabled -#include +//#include // standard Visual Studio leak check disabled, //# define _CRTDBG_MAP_ALLOC //# include From e08d8642f441f6e123f86dd881164082a9def5f5 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 26 Oct 2008 10:13:07 +0300 Subject: [PATCH 005/256] Updated DBC files structure --- src/shared/Database/DBCStores.cpp | 49 +- src/shared/Database/DBCStores.h | 7 + src/shared/Database/DBCStructure.h | 735 ++++++++++++++++------------- src/shared/Database/DBCfmt.cpp | 45 +- 4 files changed, 481 insertions(+), 355 deletions(-) diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp index fc5274cc3..b24aedf37 100644 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -36,6 +36,7 @@ static AreaFlagByMapID sAreaFlagByMapID; // for instances wit DBCStorage sAreaTriggerStore(AreaTriggerEntryfmt); DBCStorage sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt); DBCStorage sBattlemasterListStore(BattlemasterListEntryfmt); +DBCStorage sBarberShopStyleStore(BarberShopStyleEntryfmt); DBCStorage sCharTitlesStore(CharTitlesEntryfmt); DBCStorage sChatChannelsStore(ChatChannelsEntryfmt); DBCStorage sChrClassesStore(ChrClassesEntryfmt); @@ -55,7 +56,10 @@ DBCStorage sFactionStore(FactionEntryfmt); DBCStorage sFactionTemplateStore(FactionTemplateEntryfmt); DBCStorage sGemPropertiesStore(GemPropertiesEntryfmt); +DBCStorage sGlyphPropertiesStore(GlyphPropertiesfmt); +DBCStorage sGlyphSlotStore(GlyphSlotfmt); +DBCStorage sGtBarberShopCostBaseStore(GtBarberShopCostBasefmt); DBCStorage sGtCombatRatingsStore(GtCombatRatingsfmt); DBCStorage sGtChanceToMeleeCritBaseStore(GtChanceToMeleeCritBasefmt); DBCStorage sGtChanceToMeleeCritStore(GtChanceToMeleeCritfmt); @@ -81,6 +85,8 @@ DBCStorage sMapStore(MapEntryfmt); DBCStorage sQuestSortStore(QuestSortEntryfmt); DBCStorage sRandomPropertiesPointsStore(RandomPropertiesPointsfmt); +DBCStorage sScalingStatDistributionStore(ScalingStatDistributionfmt); +DBCStorage sScalingStatValuesStore(ScalingStatValuesfmt); DBCStorage sSkillLineStore(SkillLinefmt); DBCStorage sSkillLineAbilityStore(SkillLineAbilityfmt); @@ -98,6 +104,7 @@ DBCStorage sSpellDurationStore(SpellDurationfmt); DBCStorage sSpellFocusObjectStore(SpellFocusObjectfmt); DBCStorage sSpellRadiusStore(SpellRadiusfmt); DBCStorage sSpellRangeStore(SpellRangefmt); +DBCStorage sSpellRuneCostStore(SpellRuneCostfmt); DBCStorage sSpellShapeshiftStore(SpellShapeshiftfmt); DBCStorage sStableSlotPricesStore(StableSlotPricesfmt); DBCStorage sTalentStore(TalentEntryfmt); @@ -175,7 +182,7 @@ void LoadDBCStores(std::string dataPath) { std::string dbcPath = dataPath+"dbc/"; - const uint32 DBCFilesCount = 56; + const uint32 DBCFilesCount = 60; barGoLink bar( DBCFilesCount ); @@ -201,6 +208,7 @@ void LoadDBCStores(std::string dataPath) LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaTriggerStore, dbcPath,"AreaTrigger.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,sCharTitlesStore, dbcPath,"CharTitles.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChatChannelsStore, dbcPath,"ChatChannels.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrClassesStore, dbcPath,"ChrClasses.dbc"); @@ -224,7 +232,10 @@ void LoadDBCStores(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"); @@ -249,6 +260,8 @@ void LoadDBCStores(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"); @@ -298,6 +311,7 @@ void LoadDBCStores(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,sTalentStore, dbcPath,"Talent.dbc"); @@ -402,7 +416,10 @@ void LoadDBCStores(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) @@ -433,20 +450,20 @@ void LoadDBCStores(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 at up-to-date DBC files (54909 is last added spell in 3.0.1) + // check at up-to-date DBC files (19162 is last added spell in abilities in 3.0.1) + // check at up-to-date DBC files (619 is last map added in 3.0.1) + // check at up-to-date DBC files (1361 is last gem property added in 3.0.1) + // check at up-to-date DBC files (2425 is last item extended cost added in 3.0.1) + // check at up-to-date DBC files (76 is last char title added in 3.0.1) + // check at up-to-date DBC files (2311 is last area added in 3.0.1) + if( !sSpellStore.LookupEntry(54909) || + !sSkillLineAbilityStore.LookupEntry(19162) || + !sMapStore.LookupEntry(619) || + !sGemPropertiesStore.LookupEntry(1361) || + !sItemExtendedCostStore.LookupEntry(2425) || + !sCharTitlesStore.LookupEntry(76) || + !sAreaStore.LookupEntry(2311) ) { sLog.outError("\nYou have _outdated_ DBC files. Please extract correct versions from current using client."); exit(1); diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h index 041281e5a..03820d1f0 100644 --- a/src/shared/Database/DBCStores.h +++ b/src/shared/Database/DBCStores.h @@ -132,6 +132,7 @@ class DBCStorage extern DBCStorage sAreaStore;// recommend access using functions extern DBCStorage sAreaTriggerStore; extern DBCStorage sBankBagSlotPricesStore; +extern DBCStorage sBarberShopStyleStore; extern DBCStorage sBattlemasterListStore; //extern DBCStorage sChatChannelsStore; -- accessed using function, no usable index extern DBCStorage sCharTitlesStore; @@ -146,7 +147,10 @@ extern DBCStorage sEmotesTextStore; extern DBCStorage sFactionStore; extern DBCStorage sFactionTemplateStore; extern DBCStorage sGemPropertiesStore; +extern DBCStorage sGlyphPropertiesStore; +extern DBCStorage sGlyphSlotStore; +extern DBCStorage sGtBarberShopCostBaseStore; extern DBCStorage sGtCombatRatingsStore; extern DBCStorage sGtChanceToMeleeCritBaseStore; extern DBCStorage sGtChanceToMeleeCritStore; @@ -167,6 +171,8 @@ extern DBCStorage sMailTemplateStore; extern DBCStorage sMapStore; extern DBCStorage sQuestSortStore; extern DBCStorage sRandomPropertiesPointsStore; +extern DBCStorage sScalingStatDistributionStore; +extern DBCStorage sScalingStatValuesStore; extern DBCStorage sSkillLineStore; extern DBCStorage sSkillLineAbilityStore; extern DBCStorage sSoundEntriesStore; @@ -179,6 +185,7 @@ extern SpellCategoryStore sSpellCategoryStore; extern PetFamilySpellsStore sPetFamilySpellsStore; extern DBCStorage sSpellRadiusStore; extern DBCStorage sSpellRangeStore; +extern DBCStorage sSpellRuneCostStore; extern DBCStorage sSpellShapeshiftStore; extern DBCStorage sSpellStore; extern DBCStorage sStableSlotPricesStore; diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 61d4f9eb5..9158bd3c7 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -37,69 +37,84 @@ 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 + 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 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 extent x edge + float box_y; // 7 m_box_width extent y edge + float box_z; // 8 m_box_heigh extent z edge + float box_orientation; // 9 m_box_yaw extent rotation by about z axis }; 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 unk3; // 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 }; 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< + + + + diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj index 09e58cfad..dd2952950 100644 --- a/win/VC90/game.vcproj +++ b/win/VC90/game.vcproj @@ -6,6 +6,7 @@ ProjectGUID="{1DC6C4DA-A028-41F3-877D-D5400C594F88}" RootNamespace="game" Keyword="Win32Proj" + TargetFrameworkVersion="0" > + + + + From 6496f7499efd4f7fb85a3f3c64056d01fbc357f6 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Tue, 28 Oct 2008 01:44:27 +0300 Subject: [PATCH 028/256] Account data saving must work now --- .../5_character_account_data.sql | 8 ++--- src/game/CharacterHandler.cpp | 3 +- src/game/MiscHandler.cpp | 16 ++++----- src/game/NPCHandler.cpp | 2 +- src/game/Object.h | 4 ++- src/game/Opcodes.h | 12 +++---- src/game/Player.cpp | 25 ------------- src/game/Player.h | 23 +----------- src/game/SharedDefines.h | 1 - src/game/WorldSession.cpp | 35 +++++++++++++++++++ src/game/WorldSession.h | 25 +++++++++++++ src/game/WorldSocket.cpp | 2 ++ src/shared/Database/Database.h | 2 +- 13 files changed, 87 insertions(+), 71 deletions(-) diff --git a/sql/wotlk_updates/5_character_account_data.sql b/sql/wotlk_updates/5_character_account_data.sql index 7e6fa8f11..08b9a5b5b 100644 --- a/sql/wotlk_updates/5_character_account_data.sql +++ b/sql/wotlk_updates/5_character_account_data.sql @@ -1,7 +1,7 @@ CREATE TABLE `account_data` ( - `guid` int(11) unsigned NOT NULL default '0', + `account` int(11) unsigned NOT NULL default '0', `type` int(11) unsigned NOT NULL default '0', `time` bigint(11) unsigned NOT NULL default '0', - `data` longtext NOT NULL default '', - PRIMARY KEY (`guid`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file + `data` longtext NOT NULL, + PRIMARY KEY (`account`,`type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index d665e6dc8..ace5be7c7 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -79,7 +79,6 @@ bool LoginQueryHolder::Initialize() res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid)); // 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_LOADACCOUNTDATA, "SELECT type,time,data FROM account_data WHERE guid = '%u'", GUID_LOPART(m_guid)); return res; } @@ -502,7 +501,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) data << uint32(time(NULL)); // unix time of something data << uint8(1); for(int i = 0; i < NUM_ACCOUNT_DATA_TYPES; i++) - data << uint32(pCurrChar->GetAccountData(i)->Time); // also unix time + data << uint32(GetAccountData(i)->Time); // also unix time SendPacket(&data); data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 389807597..44c34f5d1 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1081,8 +1081,8 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) if(decompressedSize == 0) // erase { - _player->SetAccountData(type, timestamp, ""); - _player->SaveAccountData(type); + SetAccountData(type, timestamp, ""); + SaveAccountData(type); return; } @@ -1099,8 +1099,8 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) std::string adata; dest >> adata; - _player->SetAccountData(type, timestamp, adata); - _player->SaveAccountData(type); + SetAccountData(type, timestamp, adata); + SaveAccountData(type); WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); data << uint32(type); @@ -1121,18 +1121,18 @@ void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) if(type > NUM_ACCOUNT_DATA_TYPES) return; - AccountData *adata = _player->GetAccountData(type); + AccountData *adata = GetAccountData(type); uint32 size = adata->Data.size(); - uLongf destSize = compressBound(size); + uLongf destSize = size; ByteBuffer dest; + dest.resize(size); - //if(compress(const_cast(dest.contents()), &destSize, const_cast(adata->Data.c_str()), size) != Z_OK) if(compress(const_cast(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK) { sLog.outDebug("RAD: Failed to compress account data, error"); return; } - + dest.resize(destSize); WorldPacket data (SMSG_UPDATE_ACCOUNT_DATA, 8+4+4+4+destSize); diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index f9ab1ded7..cc2fb033c 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -552,7 +552,7 @@ void WorldSession::HandleStablePet( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 8); - sLog.outDebug("WORLD: Recv CMSG_STABLE_PET not dispose."); + sLog.outDebug("WORLD: Recv CMSG_STABLE_PET"); uint64 npcGUID; recv_data >> npcGUID; diff --git a/src/game/Object.h b/src/game/Object.h index 9358996fe..ce905cb50 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -242,7 +242,9 @@ class MANGOS_DLL_SPEC Object { ASSERT( index < m_valuesCount || PrintIndexError( index , false ) ); ASSERT( offset < 4 ); - return (((uint8*)m_uint32Values[index])[offset] & flag) != 0; + //return *(((uint16*)&m_uint32Values[ index ])+offset); + //return (((uint8*)m_uint32Values[index])[offset] & flag) != 0; + return (((uint8*)&m_uint32Values[index])[offset] & flag) != 0; } void ApplyModFlag( uint16 index, uint32 flag, bool apply) diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 9879cfea9..3ec8544e7 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1210,13 +1210,13 @@ enum Opcodes UMSG_UNKNOWN_1179 = 0x49B, // not found in client CMSG_UNKNOWN_1180 = 0x49C, // lua: HearthAndResurrectFromArea SMSG_UNKNOWN_1181 = 0x49D, // empty - SMSG_UNKNOWN_1182 = 0x49E, // uint32 - SMSG_UNKNOWN_1183 = 0x49F, // uint32 + SMSG_UNKNOWN_1182 = 0x49E, // uint32 EVENT_CRITERIA_UPDATE + SMSG_UNKNOWN_1183 = 0x49F, // uint32 EVENT_ACHIEVEMENT_EARNED UMSG_UNKNOWN_1184 = 0x4A0, // not found in client - UMSG_UNKNOWN_1185 = 0x4A1, - UMSG_UNKNOWN_1186 = 0x4A2, - UMSG_UNKNOWN_1187 = 0x4A3, - UMSG_UNKNOWN_1188 = 0x4A4, + UMSG_UNKNOWN_1185 = 0x4A1, // not found in client + UMSG_UNKNOWN_1186 = 0x4A2, // not found in client + UMSG_UNKNOWN_1187 = 0x4A3, // not found in client + UMSG_UNKNOWN_1188 = 0x4A4, // not found in client NUM_MSG_TYPES = 0x4A5 }; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 116a4dc89..a7811759c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18568,28 +18568,3 @@ void Player::InitGlyphsForLevel() SetUInt32Value(PLAYER_GLYPHS_ENABLED, value); } - -void Player::LoadAccountData(QueryResult *result) -{ - do - { - Field *fields = result->Fetch(); - - AccountData data; - uint32 type = fields[0].GetUInt32(); - data.Time = fields[1].GetUInt32(); - data.Data = fields[2].GetCppString(); - - if(type < NUM_ACCOUNT_DATA_TYPES) - m_accountData[type] = data; - } while (result->NextRow()); - - delete result; -} - -void Player::SaveAccountData(uint32 type) -{ - uint32 lowguid = GetGUIDLow(); - CharacterDatabase.PExecute("DELETE FROM account_data WHERE guid=%u AND type=%u", lowguid, type); - CharacterDatabase.PExecute("INSERT INTO account_data VALUES (%u,%u,%u,%s)", lowguid, type, (uint32)m_accountData[type].Time, m_accountData[type].Data.c_str()); -} diff --git a/src/game/Player.h b/src/game/Player.h index d7432d1e6..4d6c883e0 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -221,12 +221,6 @@ struct Areas float y2; }; -struct AccountData -{ - time_t Time; - std::string Data; -}; - enum FactionFlags { FACTION_FLAG_VISIBLE = 0x01, // makes visible in client (set or can be set at interaction with target of this faction) @@ -841,10 +835,9 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS = 15, PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16, PLAYER_LOGIN_QUERY_LOADGUILD = 17, - PLAYER_LOGIN_QUERY_LOADACCOUNTDATA = 18, }; -#define MAX_PLAYER_LOGIN_QUERY 19 +#define MAX_PLAYER_LOGIN_QUERY 18 // Player summoning auto-decline time (in secs) #define MAX_PLAYER_SUMMON_DELAY (2*MINUTE) @@ -1352,18 +1345,6 @@ class MANGOS_DLL_SPEC Player : public Unit } } - AccountData *GetAccountData(uint32 type) - { - return &m_accountData[type]; - } - void SetAccountData(uint32 type, time_t time_, std::string data) - { - m_accountData[type].Time = time_; - m_accountData[type].Data = data; - } - void LoadAccountData(QueryResult *result); - void SaveAccountData(uint32 type); - QuestStatusMap& getQuestStatusMap() { return mQuestStatus; }; const uint64& GetSelection( ) const { return m_curSelection; } @@ -2236,8 +2217,6 @@ class MANGOS_DLL_SPEC Player : public Unit uint32 m_Tutorials[8]; bool m_TutorialsChanged; - AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES]; - bool m_DailyQuestChanged; time_t m_lastDailyQuestTime; diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index f97a747a3..8b942dfd4 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -82,7 +82,6 @@ enum Classes #define CLASSMASK_WAND_USERS ((1<<(CLASS_PRIEST-1))|(1<<(CLASS_MAGE-1))|(1<<(CLASS_WARLOCK-1))) #define PLAYER_MAX_BATTLEGROUND_QUEUES 3 -#define NUM_ACCOUNT_DATA_TYPES 8 enum ReputationRank { diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 6cc0894da..7e08e0871 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -509,3 +509,38 @@ 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::SaveAccountData(uint32 type) +{ + uint32 acc = GetAccountId(); + CharacterDatabase.PExecute("DELETE FROM account_data WHERE account='%u' AND type='%u'", acc, type); + CharacterDatabase.PExecute("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)m_accountData[type].Time, m_accountData[type].Data.c_str()); +} diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 0ce24f429..5465d2664 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -44,6 +44,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(NULL), Data("") {} + + time_t Time; + std::string Data; +}; + enum PartyOperation { PARTY_OP_INVITE = 0, @@ -147,6 +157,20 @@ class MANGOS_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) + { + m_accountData[type].Time = time_; + m_accountData[type].Data = data; + } + + void LoadAccountData(); + void SaveAccountData(uint32 type); + //mail //used with item_page table bool SendItemInfo( uint32 itemid, WorldPacket data ); @@ -661,6 +685,7 @@ class MANGOS_DLL_SPEC WorldSession LocaleConstant m_sessionDbcLocale; int m_sessionDbLocaleIndex; uint32 m_latency; + AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES]; ZThread::LockedQueue _recvQueue; }; diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index e8b11cb99..be9a05fe8 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -876,6 +876,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)); diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index 3fd319ffe..fdec33473 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -31,7 +31,7 @@ class SqlQueryHolder; typedef HM_NAMESPACE::hash_map TransactionQueues; typedef HM_NAMESPACE::hash_map QueryQueues; -#define MAX_QUERY_LEN 1024 +#define MAX_QUERY_LEN 5*1024 class MANGOS_DLL_SPEC Database { From deccb566aea0f5851311b5e055c0a2e052eb9dbf Mon Sep 17 00:00:00 2001 From: arrai Date: Tue, 28 Oct 2008 00:06:52 +0100 Subject: [PATCH 029/256] Further work on the achievement system Implemented ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT Fixed SMSG_CRITERIA_UPDATE structure Implemented parts of ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL - there are still some unknown additional conditions for this criteria type Fixed sAchievementStore lookup errors caused by an invalid DBCfmt --- src/game/AchievementMgr.cpp | 112 +++++++++++++++++++++++++++++++-- src/game/AchievementMgr.h | 22 ++++++- src/game/ItemHandler.cpp | 1 + src/game/ObjectMgr.h | 2 +- src/game/Player.cpp | 10 ++- src/game/Player.h | 5 +- src/shared/Database/DBCfmt.cpp | 4 +- 7 files changed, 138 insertions(+), 18 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 170e1a8c4..c490c9dd8 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -20,6 +20,8 @@ #include "Common.h" #include "Player.h" #include "WorldPacket.h" +#include "Database/DBCEnums.h" +#include "ObjectMgr.h" AchievementMgr::AchievementMgr(Player *player) { @@ -38,6 +40,7 @@ void AchievementMgr::LoadFromDB() void AchievementMgr::SendAchievementEarned(uint32 achievementId) { + sLog.outString("AchievementMgr::SendAchievementEarned(%u)", achievementId); WorldPacket data(SMSG_MESSAGECHAT, 200); data << uint8(CHAT_MSG_ACHIEVEMENT); data << uint32(LANG_UNIVERSAL); @@ -60,13 +63,114 @@ void AchievementMgr::SendAchievementEarned(uint32 achievementId) void AchievementMgr::SendCriteriaUpdate(uint32 criteriaId, uint32 counter) { + sLog.outString("AchievementMgr::SendCriteriaUpdate(%u, %u)", criteriaId, counter); WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8); data << uint32(criteriaId); - data << uint8(counter); - data << uint8(counter);// 2 times? + + // the counter is packed like a packed Guid + data.appendPackGUID(counter); + data.append(GetPlayer()->GetPackGUID()); - data << uint64(0x0000000); // unknown, same as in SMSG_EARNED_ACHIEVEMENT, static for every player? - data << uint32(0); // unknown, 0 + /* + data << uint32(counter); + data << uint32(counter+1);//timer1 + data << uint32(counter+2);//timer2 + */ + data << uint32(0); + data << uint32(0); + data << uint32(0); + data << uint32(0); GetPlayer()->SendMessageToSet(&data, true); } +/** + * this function will be called whenever the user might have done a criteria relevant action + */ +void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, uint32 time) +{ + sLog.outString("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time); + AchievementCriteriaEntryList const& achievementCriteriaList = objmgr.GetAchievementCriteriaByType(type); + for(AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i!=achievementCriteriaList.end(); ++i) + { + AchievementCriteriaEntry const *achievementCriteria = (*i); + switch (type) + { + case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: + case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: + SetCriteriaProgress(achievementCriteria, miscvalue1); + break; + default: + return; + } + 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; + + switch(achievementCriteria->requiredType) + { + case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: + return m_criteriaProgress[achievementCriteria->ID] >= achievementCriteria->reach_level.level; + case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: + return m_criteriaProgress[achievementCriteria->ID] >= achievementCriteria->buy_bank_slot.numberOfSlots; + + } + 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) + { + CompletedAchievement(achievement); + return; + } + + // Check if there are also other critiera which have to be fulfilled for that achievement + for (uint32 entryId = 0; entryIdreferredAchievement!= achievement->ID) + continue; + + // found an outstanding criteria, return + if(!IsCompletedCriteria(criteria)) + return; + } + CompletedAchievement(achievement); +} + +void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue) +{ + sLog.outString("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue); + m_criteriaProgress[entry->ID] = newValue; + SendCriteriaUpdate(entry->ID, newValue); +} + +void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) +{ + sLog.outString("AchievementMgr::CompletedAchievement(%u)", achievement->ID); + if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER || m_completedAchievements.find(achievement->ID)!=m_completedAchievements.end()) + return; + + SendAchievementEarned(achievement->ID); + m_completedAchievements.insert(achievement->ID); + // TODO: reward titles and items +} + diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index 7e7b6ccf2..a374b7d7c 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -18,7 +18,14 @@ #ifndef __MANGOS_ACHIEVEMENTMGR_H #define __MANGOS_ACHIEVEMENTMGR_H -#include "Player.h" +#include "Common.h" +#include "Database/DBCEnums.h" +#include "Database/DBCStores.h" + +typedef HM_NAMESPACE::hash_map CriteriaProgressMap; +typedef std::set CompletedAchievementSet; + +class Player; class AchievementMgr { @@ -27,13 +34,22 @@ class AchievementMgr void LoadFromDB(); void SaveToDB(); - void SendAchievementEarned(uint32 achievementId); - void SendCriteriaUpdate(uint32 criteriaId, uint32 counter); + void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, uint32 time=0); Player* GetPlayer() { return m_player;} private: + void SendAchievementEarned(uint32 achievementId); + void SendCriteriaUpdate(uint32 criteriaId, uint32 counter); + void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue); + void CompletedCriteria(AchievementCriteriaEntry const* entry); + void CompletedAchievement(AchievementEntry const* entry); + bool IsCompletedCriteria(AchievementCriteriaEntry const* entry); + Player* m_player; + CriteriaProgressMap m_criteriaProgress; + CompletedAchievementSet m_completedAchievements; + }; diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 46855179f..3a6083b0d 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -805,6 +805,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)); } diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index bdf15399a..b75918419 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -744,6 +744,7 @@ class ObjectMgr bool RemoveVendorItem(uint32 entry,uint32 item); bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set* skip_vendors = NULL ) const; void LoadAchievementCriteriaList(); + AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type); protected: uint32 m_auctionid; @@ -810,7 +811,6 @@ class ObjectMgr int DBCLocaleIndex; - AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type); private: void LoadScripts(ScriptMapMap& scripts, char const* tablename); void ConvertCreatureAddonAuras(CreatureDataAddon* addon, char const* table, char const* guidEntryStr); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a7811759c..da02a58e5 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -246,7 +246,7 @@ const int32 Player::ReputationRank_Length[MAX_REPUTATION_RANK] = {36000, 3000, 3 UpdateMask Player::updateVisualBits; -Player::Player (WorldSession *session): Unit() +Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) { m_transport = 0; @@ -421,7 +421,6 @@ Player::Player (WorldSession *session): Unit() m_contestedPvPTimer = 0; m_declinedname = NULL; - m_achievementMgr = NULL; } Player::~Player () @@ -468,7 +467,6 @@ Player::~Player () itr->second.save->RemovePlayer(this); delete m_declinedname; - delete m_achievementMgr; } void Player::CleanupsBeforeDelete() @@ -2146,6 +2144,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, level); } void Player::InitTalentForLevel() @@ -13974,8 +13973,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) m_social = sSocialMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSOCIALLIST), GetGUIDLow()); - m_achievementMgr = new AchievementMgr(this); - m_achievementMgr->LoadFromDB(); + m_achievementMgr.LoadFromDB(); if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND))) return false; @@ -15196,7 +15194,7 @@ void Player::SaveToDB() // save pet (hunter pet level and experience and all type pets health/mana). if(Pet* pet = GetPet()) pet->SavePetToDB(PET_SAVE_AS_CURRENT); - m_achievementMgr->SaveToDB(); + m_achievementMgr.SaveToDB(); } // fast save function for item/money cheating preventing - save only inventory and money state diff --git a/src/game/Player.h b/src/game/Player.h index 4d6c883e0..c94242cbb 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -32,6 +32,7 @@ #include "WorldSession.h" #include "Pet.h" #include "Util.h" // for Tokens typedef +#include "AchievementMgr.h" #include #include @@ -2055,7 +2056,7 @@ class MANGOS_DLL_SPEC Player : public Unit DeclinedName const* GetDeclinedNames() const { return m_declinedname; } - AchievementMgr *GetAchievementMgr() { return m_achievementMgr; } + AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } protected: /*********************************************************/ @@ -2286,7 +2287,7 @@ class MANGOS_DLL_SPEC Player : public Unit WorldLocation m_teleport_dest; DeclinedName *m_declinedname; - AchievementMgr *m_achievementMgr; + 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; diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 2bb6375a1..a4738330c 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -16,8 +16,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -const char Achievementfmt[]="iiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiixxixxxxxxxxxxxxxxxxxxx"; -const char AchievementCriteriafmt[]="iiiiiiiiixxxxxxxxxxxxxxxxxiixix"; +const char Achievementfmt[]="niixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiixxixxxxxxxxxxxxxxxxxxx"; +const char AchievementCriteriafmt[]="niiiiiiiixxxxxxxxxxxxxxxxxiixix"; const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxixxxxxxx"; const char AreaTriggerEntryfmt[]="niffffffff"; const char BankBagSlotPricesEntryfmt[]="ni"; From 1167c55bd9cd7a8cbd0ed43282bfcff6dcb20474 Mon Sep 17 00:00:00 2001 From: arrai Date: Tue, 28 Oct 2008 22:15:41 +0100 Subject: [PATCH 030/256] Fixed several achievement related packets --- src/game/AchievementMgr.cpp | 112 +++++++++++++++++++++++++++++------- src/game/AchievementMgr.h | 11 +++- src/game/Player.cpp | 7 ++- 3 files changed, 104 insertions(+), 26 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index c490c9dd8..67c1932ef 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -22,6 +22,7 @@ #include "WorldPacket.h" #include "Database/DBCEnums.h" #include "ObjectMgr.h" +#include "Guild.h" AchievementMgr::AchievementMgr(Player *player) { @@ -41,23 +42,40 @@ void AchievementMgr::LoadFromDB() void AchievementMgr::SendAchievementEarned(uint32 achievementId) { sLog.outString("AchievementMgr::SendAchievementEarned(%u)", achievementId); + WorldPacket data(SMSG_MESSAGECHAT, 200); data << uint8(CHAT_MSG_ACHIEVEMENT); data << uint32(LANG_UNIVERSAL); data << uint64(GetPlayer()->GetGUID()); - data << uint32(0); + data << uint32(5); data << uint64(GetPlayer()->GetGUID()); const char *msg = "|Hplayer:$N|h[$N]|h has earned the achievement $a!"; - data << uint32(strlen(msg)); + data << uint32(strlen(msg)+1); data << msg; data << uint8(0); data << uint32(achievementId); GetPlayer()->SendMessageToSet(&data, true); + if(Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId())) + { + data.Initialize(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(achievementId); + guild->BroadcastPacket(&data); + } + data.Initialize(SMSG_ACHIEVEMENT_EARNED, 8+4+8); data.append(GetPlayer()->GetPackGUID()); data << uint32(achievementId); - data << uint64(0x0000000); // magic number? same as in SMSG_CRITERIA_UPDATE. static for every player? + data << uint32(secsToTimeBitFields(time(NULL))); + data << uint32(0); GetPlayer()->SendMessageToSet(&data, true); } @@ -71,18 +89,23 @@ void AchievementMgr::SendCriteriaUpdate(uint32 criteriaId, uint32 counter) data.appendPackGUID(counter); data.append(GetPlayer()->GetPackGUID()); - /* - data << uint32(counter); - data << uint32(counter+1);//timer1 - data << uint32(counter+2);//timer2 - */ - data << uint32(0); - data << uint32(0); - data << uint32(0); data << uint32(0); + data << uint32(secsToTimeBitFields(time(NULL))); + 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; igetLevel()); + break; case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: - SetCriteriaProgress(achievementCriteria, miscvalue1); - break; + SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1); + break; default: return; } @@ -136,24 +161,29 @@ void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria) if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) return; - if(criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL) + if(criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL || IsCompletedAchievement(achievement)) { CompletedAchievement(achievement); - return; } +} - // Check if there are also other critiera which have to be fulfilled for that achievement +bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* achievement) +{ + bool foundOutstanding = false; for (uint32 entryId = 0; entryIdreferredAchievement!= achievement->ID) continue; - // found an outstanding criteria, return + if(IsCompletedCriteria(criteria) && criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL) + return true; + + // found an umcompleted criteria, but DONT return false - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL if(!IsCompletedCriteria(criteria)) - return; + foundOutstanding = true; } - CompletedAchievement(achievement); + return !foundOutstanding; } void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue) @@ -170,7 +200,49 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) return; SendAchievementEarned(achievement->ID); - m_completedAchievements.insert(achievement->ID); + m_completedAchievements[achievement->ID] = time(NULL); // TODO: reward titles and items } +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_ALL_ACHIEVEMENT_DATA,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::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); ++iter) + { + *data << uint32(iter->first); + *data << uint32(secsToTimeBitFields(iter->second)); + } + *data << int32(-1); + for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) + { + *data << uint32(iter->first); + data->appendPackGUID(iter->second); + data->append(GetPlayer()->GetPackGUID()); + *data << uint32(0); + *data << uint32(secsToTimeBitFields(time(NULL))); + *data << uint32(0); + *data << uint32(0); + } + *data << int32(-1); + +} + diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index a374b7d7c..9dfb03bcc 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -23,9 +23,10 @@ #include "Database/DBCStores.h" typedef HM_NAMESPACE::hash_map CriteriaProgressMap; -typedef std::set CompletedAchievementSet; +typedef HM_NAMESPACE::hash_map CompletedAchievementMap; class Player; +class WorldPacket; class AchievementMgr { @@ -35,6 +36,9 @@ class AchievementMgr void LoadFromDB(); void SaveToDB(); void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, uint32 time=0); + void CheckAllAchievementCriteria(); + void SendAllAchievementData(); + void SendRespondInspectAchievements(Player* player); Player* GetPlayer() { return m_player;} @@ -45,11 +49,12 @@ class AchievementMgr void CompletedCriteria(AchievementCriteriaEntry const* entry); void CompletedAchievement(AchievementEntry const* entry); bool IsCompletedCriteria(AchievementCriteriaEntry const* entry); + bool IsCompletedAchievement(AchievementEntry const* entry); + void BuildAllDataPacket(WorldPacket *data); Player* m_player; CriteriaProgressMap m_criteriaProgress; - CompletedAchievementSet m_completedAchievements; - + CompletedAchievementMap m_completedAchievements; }; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index d17f47657..b4053002c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2142,7 +2142,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, level); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL); } void Player::InitTalentForLevel() @@ -13971,8 +13971,6 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) m_social = sSocialMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSOCIALLIST), GetGUIDLow()); - m_achievementMgr.LoadFromDB(); - if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND))) return false; @@ -14090,6 +14088,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadDeclinedNames(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES)); + m_achievementMgr.LoadFromDB(); + m_achievementMgr.CheckAllAchievementCriteria(); return true; } @@ -17459,6 +17459,7 @@ void Player::SendInitialPacketsBeforeAddToMap() SendInitialActionButtons(); SendInitialReputations(); + m_achievementMgr.SendAllAchievementData(); UpdateZone(GetZoneId()); SendInitWorldStates(); From 5364fc28477e91d65085ef90f6df4a71169ab74f Mon Sep 17 00:00:00 2001 From: arrai Date: Wed, 29 Oct 2008 12:17:37 +0100 Subject: [PATCH 031/256] Removed wrong assumed flag, use achievement points to differ between achievements and counters --- src/game/AchievementMgr.cpp | 11 ++++++++--- src/shared/Database/DBCEnums.h | 2 -- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 67c1932ef..6b98d633c 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -116,6 +116,11 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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; + switch (type) { case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: @@ -138,7 +143,7 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve if(!achievement) return false; // counter can never complete - if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) + if(achievement->points == 0) return false; switch(achievementCriteria->requiredType) @@ -158,7 +163,7 @@ void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria) if(!achievement) return; // counter can never complete - if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) + if(achievement->points ==0) return; if(criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL || IsCompletedAchievement(achievement)) @@ -196,7 +201,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) { sLog.outString("AchievementMgr::CompletedAchievement(%u)", achievement->ID); - if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER || m_completedAchievements.find(achievement->ID)!=m_completedAchievements.end()) + if(achievement->points==0 || m_completedAchievements.find(achievement->ID)!=m_completedAchievements.end()) return; SendAchievementEarned(achievement->ID); diff --git a/src/shared/Database/DBCEnums.h b/src/shared/Database/DBCEnums.h index b0e77efcc..03ab622a8 100644 --- a/src/shared/Database/DBCEnums.h +++ b/src/shared/Database/DBCEnums.h @@ -34,8 +34,6 @@ enum AchievementFactionFlags enum AchievementFlags { - // This achievement is a counter and can never be "fulfilled" - ACHIEVEMENT_FLAG_COUNTER = 0x00000001, }; enum AchievementCriteriaCompletionFlags From ca6e456da1f4201e539b0c06af2674e48b9e30b7 Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 28 Oct 2008 21:10:08 +0100 Subject: [PATCH 032/256] Added missed part from my prev. commit. Compile fix. Signed-off-by: ApoC --- src/game/Group.cpp | 10 ++++++++++ src/game/Group.h | 10 +--------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/game/Group.cpp b/src/game/Group.cpp index d850fcfee..36bccee2f 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -195,6 +195,16 @@ bool Group::LoadMemberFromDB(uint32 guidLow, uint8 subgroup, bool assistant) return true; } +void Group::ConvertToRaid() +{ + m_groupType = GROUPTYPE_RAID; + + _initRaidSubGroupsCounter(); + + if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid)); + SendUpdate(); +} + bool Group::AddInvite(Player *player) { if(!player || player->GetGroupInvite() || player->GetGroup()) diff --git a/src/game/Group.h b/src/game/Group.h index fbe0c9f22..5e909dd49 100644 --- a/src/game/Group.h +++ b/src/game/Group.h @@ -232,15 +232,8 @@ class MANGOS_DLL_SPEC Group } // some additional raid methods - void ConvertToRaid() - { - m_groupType = GROUPTYPE_RAID; + void ConvertToRaid(); - _initRaidSubGroupsCounter(); - - if(!isBGGroup()) CharacterDatabase.PExecute("UPDATE groups SET isRaid = 1 WHERE leaderGuid='%u'", GUID_LOPART(m_leaderGuid)); - SendUpdate(); - } void SetBattlegroundGroup(BattleGround *bg) { m_bgGroup = bg; } void ChangeMembersGroup(const uint64 &guid, const uint8 &group); @@ -330,7 +323,6 @@ class MANGOS_DLL_SPEC Group void _removeRolls(const uint64 &guid); - void _convertToRaid(); bool _setMembersGroup(const uint64 &guid, const uint8 &group); bool _setAssistantFlag(const uint64 &guid, const bool &state); bool _setMainTank(const uint64 &guid); From 8bea43063e5a1e0c4c0ade99e712aaf865efaf18 Mon Sep 17 00:00:00 2001 From: ApoC Date: Mon, 27 Oct 2008 22:36:42 +0100 Subject: [PATCH 033/256] Added checking global cooldown for pet autocast spells. Added checking global cooldown for pet spell casting triggered by master. Optimized PetAI::UpdateAI: - Removed obsolete victim_guid as combat check. - Stop pet combat when pet die in JustDied(Unit*) method. - Optimized autospells selection and casting. Signed-off-by: ApoC --- src/game/Creature.h | 2 + src/game/PetAI.cpp | 191 +++++++++++++++++++--------------------- src/game/PetAI.h | 11 ++- src/game/PetHandler.cpp | 6 ++ 4 files changed, 106 insertions(+), 104 deletions(-) diff --git a/src/game/Creature.h b/src/game/Creature.h index 4f2a48b2b..f6cb5365d 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -570,6 +570,8 @@ class MANGOS_DLL_SPEC Creature : public Unit void SetCombatStartPosition(float x, float y, float z) { CombatStartX = x; CombatStartY = y; CombatStartZ = z; } void GetCombatStartPosition(float &x, float &y, float &z) { x = CombatStartX; y = CombatStartY; z = CombatStartZ; } + uint32 GetGlobalCooldown() const { return m_GlobalCooldown; } + protected: bool CreateFromProto(uint32 guidlow,uint32 Entry,uint32 team, const CreatureData *data = NULL); bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL); diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 81ca6889f..144b2d7f8 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -36,7 +36,7 @@ int PetAI::Permissible(const Creature *creature) return PERMIT_BASE_NO; } -PetAI::PetAI(Creature &c) : i_pet(c), i_victimGuid(0), i_tracker(TIME_INTERVAL_LOOK) +PetAI::PetAI(Creature &c) : i_pet(c), i_tracker(TIME_INTERVAL_LOOK), inCombat(false) { m_AllySet.clear(); UpdateAllies(); @@ -63,7 +63,7 @@ void PetAI::MoveInLineOfSight(Unit *u) void PetAI::AttackStart(Unit *u) { - if( i_pet.getVictim() || !u || i_pet.isPet() && ((Pet&)i_pet).getPetType()==MINI_PET ) + if( inCombat || !u || (i_pet.isPet() && ((Pet&)i_pet).getPetType() == MINI_PET) ) return; if(i_pet.Attack(u,true)) @@ -73,8 +73,8 @@ void PetAI::AttackStart(Unit *u) // thus with the following clear the original TMG gets invalidated and crash, doh // hope it doesn't start to leak memory without this :-/ //i_pet->Clear(); - i_victimGuid = u->GetGUID(); i_pet.GetMotionMaster()->MoveChase(u); + inCombat = true; } } @@ -89,9 +89,6 @@ bool PetAI::IsVisible(Unit *pl) const bool PetAI::_needToStop() const { - if(!i_pet.getVictim() || !i_pet.isAlive()) - return true; - // This is needed for charmed creatures, as once their target was reset other effects can trigger threat if(i_pet.isCharmed() && i_pet.getVictim() == i_pet.GetCharmer()) return true; @@ -101,48 +98,18 @@ bool PetAI::_needToStop() const void PetAI::_stopAttack() { - if( !i_victimGuid ) - return; - - Unit* victim = ObjectAccessor::GetUnit(i_pet, i_victimGuid ); - - if ( !victim ) - return; - - assert(!i_pet.getVictim() || i_pet.getVictim() == victim); - + inCombat = false; if( !i_pet.isAlive() ) { DEBUG_LOG("Creature stoped attacking cuz his dead [guid=%u]", i_pet.GetGUIDLow()); i_pet.StopMoving(); i_pet.GetMotionMaster()->Clear(); i_pet.GetMotionMaster()->MoveIdle(); - i_victimGuid = 0; i_pet.CombatStop(); i_pet.getHostilRefManager().deleteReferences(); return; } - else if( !victim ) - { - DEBUG_LOG("Creature stopped attacking because victim is non exist [guid=%u]", i_pet.GetGUIDLow()); - } - else if( !victim->isAlive() ) - { - DEBUG_LOG("Creature stopped attacking cuz his victim is dead [guid=%u]", i_pet.GetGUIDLow()); - } - else if( victim->HasStealthAura() ) - { - DEBUG_LOG("Creature stopped attacking cuz his victim is stealth [guid=%u]", i_pet.GetGUIDLow()); - } - else if( victim->isInFlight() ) - { - DEBUG_LOG("Creature stopped attacking cuz his victim is fly away [guid=%u]", i_pet.GetGUIDLow()); - } - else - { - DEBUG_LOG("Creature stopped attacking due to target out run him [guid=%u]", i_pet.GetGUIDLow()); - } Unit* owner = i_pet.GetCharmerOrOwner(); @@ -156,15 +123,13 @@ void PetAI::_stopAttack() i_pet.GetMotionMaster()->Clear(); i_pet.GetMotionMaster()->MoveIdle(); } - i_victimGuid = 0; i_pet.AttackStop(); } void PetAI::UpdateAI(const uint32 diff) { - // update i_victimGuid if i_pet.getVictim() !=0 and changed - if(i_pet.getVictim()) - i_victimGuid = i_pet.getVictim()->GetGUID(); + if (!i_pet.isAlive()) + return; Unit* owner = i_pet.GetCharmerOrOwner(); @@ -174,13 +139,16 @@ void PetAI::UpdateAI(const uint32 diff) else m_updateAlliesTimer -= diff; + if (inCombat && i_pet.getVictim() == NULL) + _stopAttack(); + // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. - if( i_victimGuid ) + if( i_pet.getVictim() != NULL ) { if( _needToStop() ) { DEBUG_LOG("Pet AI stoped attacking [guid=%u]", i_pet.GetGUIDLow()); - _stopAttack(); // i_victimGuid == 0 && i_pet.getVictim() == NULL now + _stopAttack(); return; } else if( i_pet.IsStopped() || i_pet.IsWithinDistInMap(i_pet.getVictim(), ATTACK_DISTANCE)) @@ -226,75 +194,96 @@ void PetAI::UpdateAI(const uint32 diff) } } - //Autocast - HM_NAMESPACE::hash_map targetMap; - targetMap.clear(); - SpellCastTargets NULLtargets; - - for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++) + if (i_pet.GetGlobalCooldown() == 0 && !i_pet.IsNonMeleeSpellCasted(false)) { - uint32 spellID = i_pet.GetPetAutoSpellOnPos(i); - if (!spellID) - continue; - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); - if (!spellInfo) - continue; - - Spell *spell = new Spell(&i_pet, spellInfo, false, 0); - - if(!IsPositiveSpell(spellInfo->Id) && i_pet.getVictim() && !_needToStop() && !i_pet.hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(i_pet.getVictim())) - targetMap[spellID] = i_pet.getVictim(); - else + //Autocast + for (uint8 i = 0; i < i_pet.GetPetAutoSpellSize(); i++) { - spell->m_targets = NULLtargets; - for(std::set::iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) - { - Unit* Target = ObjectAccessor::GetUnit(i_pet,*tar); + uint32 spellID = i_pet.GetPetAutoSpellOnPos(i); + if (!spellID) + continue; - //only buff targets that are in combat, unless the spell can only be cast while out of combat - if(!Target || (!Target->isInCombat() && !IsNonCombatSpell(spellInfo))) + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellID); + if (!spellInfo) + continue; + + // ignore some combinations of combat state and combat/noncombat spells + if (!inCombat) + { + if (!IsPositiveSpell(spellInfo->Id)) continue; - if(spell->CanAutoCast(Target)) - targetMap[spellID] = Target; + } + else + { + if (IsNonCombatSpell(spellInfo)) + continue; + } + + Spell *spell = new Spell(&i_pet, spellInfo, false, 0); + + if(inCombat && !i_pet.hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(i_pet.getVictim())) + { + m_targetSpellStore.push_back(std::make_pair(i_pet.getVictim(), spell)); + continue; + } + else + { + bool spellUsed = false; + for(std::set::iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar) + { + Unit* Target = ObjectAccessor::GetUnit(i_pet,*tar); + + //only buff targets that are in combat, unless the spell can only be cast while out of combat + if(!Target) + continue; + + if(spell->CanAutoCast(Target)) + { + m_targetSpellStore.push_back(std::make_pair(Target, spell)); + spellUsed = true; + break; + } + } + if (!spellUsed) + delete spell; } } - delete spell; - } - - //found units to cast on to - if(!targetMap.empty()) - { - uint32 index = urand(1, targetMap.size()); - HM_NAMESPACE::hash_map::iterator itr; - uint32 i; - for(itr = targetMap.begin(), i = 1; i < index; ++itr, ++i); - - SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first); - - Spell *spell = new Spell(&i_pet, spellInfo, false); - - SpellCastTargets targets; - targets.setUnitTarget( itr->second ); - - if(!i_pet.HasInArc(M_PI, itr->second)) + //found units to cast on to + if(!m_targetSpellStore.empty()) { - i_pet.SetInFront(itr->second); - if( itr->second->GetTypeId() == TYPEID_PLAYER ) - i_pet.SendUpdateToPlayer( (Player*)itr->second ); + uint32 index = urand(0, m_targetSpellStore.size() - 1); - if(owner && owner->GetTypeId() == TYPEID_PLAYER) - i_pet.SendUpdateToPlayer( (Player*)owner ); + Spell* spell = m_targetSpellStore[index].second; + Unit* target = m_targetSpellStore[index].first; + + m_targetSpellStore.erase(m_targetSpellStore.begin() + index); + + SpellCastTargets targets; + targets.setUnitTarget( target ); + + if( !i_pet.HasInArc(M_PI, target) ) + { + i_pet.SetInFront(target); + if( target->GetTypeId() == TYPEID_PLAYER ) + i_pet.SendUpdateToPlayer( (Player*)target ); + + if(owner && owner->GetTypeId() == TYPEID_PLAYER) + i_pet.SendUpdateToPlayer( (Player*)owner ); + } + + i_pet.AddCreatureSpellCooldown(spell->m_spellInfo->Id); + if(i_pet.isPet()) + ((Pet*)&i_pet)->CheckLearning(spell->m_spellInfo->Id); + + spell->prepare(&targets); + } + while (!m_targetSpellStore.empty()) + { + delete m_targetSpellStore.begin()->second; + m_targetSpellStore.erase(m_targetSpellStore.begin()); } - - i_pet.AddCreatureSpellCooldown(itr->first); - if(i_pet.isPet()) - ((Pet*)&i_pet)->CheckLearning(itr->first); - - spell->prepare(&targets); } - targetMap.clear(); } bool PetAI::_isVisible(Unit *u) const diff --git a/src/game/PetAI.h b/src/game/PetAI.h index 1b0579525..f7fc9ac13 100644 --- a/src/game/PetAI.h +++ b/src/game/PetAI.h @@ -23,6 +23,7 @@ #include "Timer.h" class Creature; +class Spell; class MANGOS_DLL_DECL PetAI : public CreatureAI { @@ -36,9 +37,9 @@ class MANGOS_DLL_DECL PetAI : public CreatureAI void DamageTaken(Unit *done_by, uint32& /*damage*/) { AttackedBy(done_by); } void AttackedBy(Unit*); bool IsVisible(Unit *) const; + void JustDied(Unit* who) { _stopAttack(); } void UpdateAI(const uint32); - void UpdateAllies(); static int Permissible(const Creature *); private: @@ -46,11 +47,15 @@ class MANGOS_DLL_DECL PetAI : public CreatureAI bool _needToStop(void) const; void _stopAttack(void); + void UpdateAllies(); + Creature &i_pet; - uint64 i_victimGuid; + bool inCombat; TimeTracker i_tracker; - //uint32 i_RepeatAction; std::set m_AllySet; uint32 m_updateAlliesTimer; + + typedef std::pair TargetSpellPair; + std::vector m_targetSpellStore; }; #endif diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index a1d5d896b..e0acefd16 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -164,6 +164,9 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) else unit_target = NULL; + if (((Creature*)pet)->GetGlobalCooldown() > 0) + return; + // do not cast unknown spells SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid ); if(!spellInfo) @@ -612,6 +615,9 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) return; } + if (pet->GetGlobalCooldown() > 0) + return; + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellid); if(!spellInfo) { From 05b8acd14027485f9b628e5da07ee9588c7c4689 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 29 Oct 2008 07:30:32 +0300 Subject: [PATCH 034/256] Small account data changes --- src/game/MiscHandler.cpp | 31 +++++++++++++++++++++---------- src/game/WorldSession.cpp | 7 +++++-- src/game/WorldSession.h | 13 ++----------- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 44c34f5d1..1e8861718 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1071,7 +1071,8 @@ void WorldSession::HandleAreaTriggerOpcode(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; @@ -1082,7 +1083,18 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) if(decompressedSize == 0) // erase { SetAccountData(type, timestamp, ""); - SaveAccountData(type); + + 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; } @@ -1092,7 +1104,7 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) uLongf realSize = decompressedSize; if(uncompress(const_cast(dest.contents()), &realSize, const_cast(recv_data.contents() + recv_data.rpos()), recv_data.size() - recv_data.rpos()) != Z_OK) { - sLog.outError("UAD: Failed to decompress packet"); + sLog.outError("UAD: Failed to decompress account data"); return; } @@ -1100,7 +1112,6 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) dest >> adata; SetAccountData(type, timestamp, adata); - SaveAccountData(type); WorldPacket data(SMSG_UPDATE_ACCOUNT_DATA_COMPLETE, 4+4); data << uint32(type); @@ -1111,7 +1122,6 @@ void WorldSession::HandleUpdateAccountData(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); @@ -1122,14 +1132,15 @@ void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) return; AccountData *adata = GetAccountData(type); - uint32 size = adata->Data.size(); - uLongf destSize = size; - ByteBuffer dest; - dest.resize(size); + uint32 size = adata->Data.size(); + + ByteBuffer dest(size); + + uLongf destSize = size; if(compress(const_cast(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK) { - sLog.outDebug("RAD: Failed to compress account data, error"); + sLog.outDebug("RAD: Failed to compress account data"); return; } diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index 136d74202..245e07b09 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -539,9 +539,12 @@ void WorldSession::LoadAccountData() delete result; } -void WorldSession::SaveAccountData(uint32 type) +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.PExecute("DELETE FROM account_data WHERE account='%u' AND type='%u'", acc, type); - CharacterDatabase.PExecute("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)m_accountData[type].Time, m_accountData[type].Data.c_str()); + CharacterDatabase.PExecute("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)time_, data.c_str()); } diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 5465d2664..58549d797 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -158,18 +158,9 @@ class MANGOS_DLL_SPEC WorldSession 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) - { - m_accountData[type].Time = time_; - m_accountData[type].Data = data; - } - + AccountData *GetAccountData(uint32 type) { return &m_accountData[type]; } + void SetAccountData(uint32 type, time_t time_, std::string data); void LoadAccountData(); - void SaveAccountData(uint32 type); //mail //used with item_page table From 5a26f822ce01aa035404c89c19089d61150f1692 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 29 Oct 2008 16:47:56 +0300 Subject: [PATCH 035/256] Some achievement*.dbc research --- src/shared/Database/DBCEnums.h | 11 +++++++++++ src/shared/Database/DBCStructure.h | 31 ++++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/shared/Database/DBCEnums.h b/src/shared/Database/DBCEnums.h index 03ab622a8..107fb26b0 100644 --- a/src/shared/Database/DBCEnums.h +++ b/src/shared/Database/DBCEnums.h @@ -36,6 +36,17 @@ enum AchievementFlags { }; +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. diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 1b7ff8da6..789d2deeb 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -40,15 +40,27 @@ struct AchievementEntry uint32 ID; // 0 uint32 factionFlag; // 1 -1=all, 0=horde, 1=alliance uint32 mapID; // 2 -1=none + //char *name[16]; // 3-19 + //uint32 name_flags; // 20 + //char *description[16]; // 21-36 + //uint32 desc_flags; // 37 uint32 categoryId; // 38 - uint32 points; // 39 - uint32 flags; // 42 + uint32 points; // 39 reward points + //uint32 OrderInCategory; // 40 + //uint32 Flags; // 41 + uint32 flags; // 42 not flags, some unknown value... + //char *unk1[16]; // 43-58 + //uint32 unk_flags; // 59 + //uint32 count; // 60 + //uint32 refAchievement; // 61 }; struct AchievementCategoryEntry { uint32 ID; // 0 uint32 parentCategory; // 1 -1 for main category + //char *name[16]; // 2-17 + //uint32 name_flags; // 18 uint32 sortOrder; // 19 }; @@ -433,17 +445,20 @@ struct AchievementCriteriaEntry struct { - uint32 field3; // 3 - uint32 field4; // 4 - uint32 field5; // 5 - uint32 field6; // 6 - uint32 field7; // 7 - uint32 field8; // 8 + uint32 field3; // 3 main requirement + uint32 field4; // 4 main requirement count + uint32 field5; // 5 additional requirement 1 type + uint32 field6; // 6 additional requirement 1 value + uint32 field7; // 7 additional requirement 2 type + uint32 field8; // 8 additional requirement 1 value } raw; }; + //char* name[16]; // 9-24 + //uint32 name_flags; // 25 uint32 completionFlag; // 26 uint32 groupFlag; // 27 uint32 timeLimit; // 29 time limit in seconds + //uint32 unk1; // 30 }; struct AreaTableEntry From cf3bbb5920e75e22f883c39bb6baaea68c50b1a0 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 29 Oct 2008 19:18:58 +0300 Subject: [PATCH 036/256] Fixed pvp flag (once again), crash fix --- sql/wotlk_updates/1_mangos_creature_equip_template.sql | 2 ++ src/game/Level3.cpp | 2 +- src/game/MiscHandler.cpp | 5 +++-- src/game/Player.cpp | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sql/wotlk_updates/1_mangos_creature_equip_template.sql b/sql/wotlk_updates/1_mangos_creature_equip_template.sql index f844f50af..fc64c1d9d 100644 --- a/sql/wotlk_updates/1_mangos_creature_equip_template.sql +++ b/sql/wotlk_updates/1_mangos_creature_equip_template.sql @@ -1,3 +1,5 @@ +TRUNCATE creature_equip_template; + alter table `creature_equip_template` drop column `equipinfo1`, drop column `equipinfo2`, diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index db4e2d8b6..42c4beb8b 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -4339,7 +4339,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_UNK3 | 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); diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 1e8861718..68b5dce0b 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -545,7 +545,7 @@ 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, newPvPStatus); + GetPlayer()->ApplyModFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP, !newPvPStatus); } else { @@ -1135,7 +1135,8 @@ void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) uint32 size = adata->Data.size(); - ByteBuffer dest(size); + ByteBuffer dest; + dest.resize(size); uLongf destSize = size; if(compress(const_cast(dest.contents()), &destSize, (uint8*)adata->Data.c_str(), size) != Z_OK) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index b4053002c..a4804d914 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -557,7 +557,7 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, SetUInt32Value(UNIT_FIELD_BYTES_0, ( ( race ) | ( class_ << 8 ) | ( gender << 16 ) | ( powertype << 24 ) ) ); SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_UNK3 | UNIT_BYTE2_FLAG_UNK5 ); + SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP ); SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); // fix cast time showed in spell tooltip on client From e92cc728c32748772458efb764726a15547aac16 Mon Sep 17 00:00:00 2001 From: arrai Date: Wed, 29 Oct 2008 17:58:56 +0100 Subject: [PATCH 037/256] Reverted wrong commit d2785283e - the real source for not matching the flags was a mixed up index in DBCfmt.cpp Added database integrity check for creature_equip_template Differ between stored and pending completed achievements --- src/game/AchievementMgr.cpp | 28 ++++++++++++++--------- src/game/AchievementMgr.h | 9 +++++++- src/game/ObjectMgr.cpp | 36 ++++++++++++++++++++++++++++++ src/game/Player.cpp | 2 +- src/shared/Database/DBCEnums.h | 1 + src/shared/Database/DBCStructure.h | 12 +++++----- src/shared/Database/DBCfmt.cpp | 2 +- 7 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 6b98d633c..998a10cb6 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -136,14 +136,17 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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->points == 0) + if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) + return false; + + if(m_criteriaProgress.find(achievementCriteria->ID) == m_criteriaProgress.end()) return false; switch(achievementCriteria->requiredType) @@ -152,7 +155,6 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve return m_criteriaProgress[achievementCriteria->ID] >= achievementCriteria->reach_level.level; case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: return m_criteriaProgress[achievementCriteria->ID] >= achievementCriteria->buy_bank_slot.numberOfSlots; - } return false; } @@ -163,32 +165,38 @@ void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria) if(!achievement) return; // counter can never complete - if(achievement->points ==0) + if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) return; - if(criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL || IsCompletedAchievement(achievement)) + if(criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL || GetAchievementCompletionState(achievement)==ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED) { CompletedAchievement(achievement); } } -bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* achievement) +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; entryIdreferredAchievement!= achievement->ID) + if(!criteria || criteria->referredAchievement!= entry->ID) continue; if(IsCompletedCriteria(criteria) && criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL) - return true; + return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED; // found an umcompleted criteria, but DONT return false - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL if(!IsCompletedCriteria(criteria)) foundOutstanding = true; } - return !foundOutstanding; + if(foundOutstanding) + return ACHIEVEMENT_COMPLETED_NONE; + else + return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED; } void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue) @@ -201,7 +209,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) { sLog.outString("AchievementMgr::CompletedAchievement(%u)", achievement->ID); - if(achievement->points==0 || m_completedAchievements.find(achievement->ID)!=m_completedAchievements.end()) + if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER || m_completedAchievements.find(achievement->ID)!=m_completedAchievements.end()) return; SendAchievementEarned(achievement->ID); diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index 9dfb03bcc..b03ba4dbf 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -28,6 +28,13 @@ typedef HM_NAMESPACE::hash_map CompletedAchievementMap; class Player; class WorldPacket; +enum AchievementCompletionState +{ + ACHIEVEMENT_COMPLETED_NONE, + ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED, + ACHIEVEMENT_COMPLETED_COMPLETED_STORED, +}; + class AchievementMgr { public: @@ -49,7 +56,7 @@ class AchievementMgr void CompletedCriteria(AchievementCriteriaEntry const* entry); void CompletedAchievement(AchievementEntry const* entry); bool IsCompletedCriteria(AchievementCriteriaEntry const* entry); - bool IsCompletedAchievement(AchievementEntry const* entry); + AchievementCompletionState GetAchievementCompletionState(AchievementEntry const* entry); void BuildAllDataPacket(WorldPacket *data); Player* m_player; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index c2efab314..ffcaeaebf 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -899,6 +899,42 @@ void ObjectMgr::LoadEquipmentTemplates() { sEquipmentStorage.Load(); + for(uint32 i=0; i< sEquipmentStorage.MaxEntry; ++i) + { + EquipmentInfo const* eqInfo = sEquipmentStorage.LookupEntry(i); + + if(!eqInfo) + continue; + + for(uint8 j=0; j<3; j++) + { + if(!eqInfo->equipentry[j]) + continue; + + ItemPrototype const* proto = objmgr.GetItemPrototype(eqInfo->equipentry[j]); + + if(!proto) + { + 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(eqInfo)->equipentry[j] = 0; + continue; + } + + if(proto->InventoryType != INVTYPE_WEAPON && + proto->InventoryType != INVTYPE_SHIELD && + proto->InventoryType != INVTYPE_RANGED && + proto->InventoryType != INVTYPE_2HWEAPON && + proto->InventoryType != INVTYPE_WEAPONMAINHAND && + proto->InventoryType != INVTYPE_WEAPONOFFHAND && + proto->InventoryType != INVTYPE_HOLDABLE && + proto->InventoryType != INVTYPE_THROWN && + proto->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(eqInfo)->equipentry[j] = 0; + } + } + } sLog.outString( ">> Loaded %u equipment template", sEquipmentStorage.RecordCount ); sLog.outString(); } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a4804d914..f54c3eddb 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1290,7 +1290,7 @@ 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()); - + 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(); diff --git a/src/shared/Database/DBCEnums.h b/src/shared/Database/DBCEnums.h index 107fb26b0..5b67af8aa 100644 --- a/src/shared/Database/DBCEnums.h +++ b/src/shared/Database/DBCEnums.h @@ -34,6 +34,7 @@ enum AchievementFactionFlags enum AchievementFlags { + ACHIEVEMENT_FLAG_COUNTER = 0x00000001, }; enum AchievementCriteriaCondition diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 789d2deeb..de3f80dfe 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -47,8 +47,8 @@ struct AchievementEntry uint32 categoryId; // 38 uint32 points; // 39 reward points //uint32 OrderInCategory; // 40 - //uint32 Flags; // 41 - uint32 flags; // 42 not flags, some unknown value... + uint32 flags; // 41 + //uint32 flags; // 42 not flags, some unknown value... //char *unk1[16]; // 43-58 //uint32 unk_flags; // 59 //uint32 count; // 60 @@ -447,10 +447,10 @@ struct AchievementCriteriaEntry { uint32 field3; // 3 main requirement uint32 field4; // 4 main requirement count - uint32 field5; // 5 additional requirement 1 type - uint32 field6; // 6 additional requirement 1 value - uint32 field7; // 7 additional requirement 2 type - uint32 field8; // 8 additional requirement 1 value + 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 diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index a4738330c..46afd6b3c 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -const char Achievementfmt[]="niixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiixxixxxxxxxxxxxxxxxxxxx"; +const char Achievementfmt[]="niixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxxx"; const char AchievementCriteriafmt[]="niiiiiiiixxxxxxxxxxxxxxxxxiixix"; const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxixxxxxxx"; const char AreaTriggerEntryfmt[]="niffffffff"; From 871d34b106a3f04aec38803a58512c3d2a0205ce Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 29 Oct 2008 20:15:35 +0300 Subject: [PATCH 038/256] Infinity loop in sendopcode command --- src/game/debugcmds.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index 02f883d20..2132e2641 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -146,6 +146,9 @@ bool ChatHandler::HandleSendOpcodeCommand(const char* args) std::string type; ifs >> type; + if(type == "") + break; + if(type == "uint8") { uint16 val1; @@ -189,6 +192,7 @@ bool ChatHandler::HandleSendOpcodeCommand(const char* args) else { sLog.outDebug("Sending opcode: unknown type %s", type.c_str()); + break; } } ifs.close(); From a1d83ebc6fcbf9e9c7f58d51d80a1f8c56e2faad Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 29 Oct 2008 23:06:45 +0300 Subject: [PATCH 039/256] Updated fot new client build 9155 --- src/game/Player.cpp | 2 +- src/game/UpdateFields.h | 2 +- src/game/debugcmds.cpp | 2 +- src/realmd/AuthCodes.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index f54c3eddb..36907d21d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3686,7 +3686,7 @@ void Player::ResurrectPlayer(float restore_percent, bool updateToWorld, bool app SetPower(POWER_ENERGY, uint32(GetMaxPower(POWER_ENERGY)*restore_percent)); } - // update visbility + // update visibility ObjectAccessor::UpdateVisibilityForPlayer(this); // some items limited to specific map diff --git a/src/game/UpdateFields.h b/src/game/UpdateFields.h index 787086bad..c5a8af86d 100644 --- a/src/game/UpdateFields.h +++ b/src/game/UpdateFields.h @@ -19,7 +19,7 @@ #ifndef _UPDATEFIELDS_AUTO_H #define _UPDATEFIELDS_AUTO_H -// Auto generated for version 3, 0, 3, 9138 +// Auto generated for version 3, 0, 3, 9155 enum EObjectFields { diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index 2132e2641..1fd67d6a0 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -191,7 +191,7 @@ bool ChatHandler::HandleSendOpcodeCommand(const char* args) } else { - sLog.outDebug("Sending opcode: unknown type %s", type.c_str()); + sLog.outDebug("Sending opcode: unknown type '%s'", type.c_str()); break; } } diff --git a/src/realmd/AuthCodes.h b/src/realmd/AuthCodes.h index 79b776ac9..0641a7064 100644 --- a/src/realmd/AuthCodes.h +++ b/src/realmd/AuthCodes.h @@ -66,8 +66,8 @@ enum LoginResult // 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 and WoW:TBC 3.0.3 client build 9135 and 9138... +// will only support WoW and WoW:TBC 3.0.3 client build 9155... -#define EXPECTED_MANGOS_CLIENT_BUILD {9135, 9138, 0} +#define EXPECTED_MANGOS_CLIENT_BUILD {9155, 0} #endif From 2af3c01a236578e2ab5aa15f10076ce6ce07a113 Mon Sep 17 00:00:00 2001 From: arrai Date: Wed, 29 Oct 2008 21:44:55 +0100 Subject: [PATCH 040/256] Implemented achievement inspection --- src/game/AchievementMgr.cpp | 6 ++++-- src/game/MiscHandler.cpp | 16 ++++++++++++++++ src/game/Opcodes.cpp | 2 +- src/game/WorldSession.h | 1 + 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 998a10cb6..e4a82c638 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -220,7 +220,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) 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); + WorldPacket data(SMSG_ALL_ACHIEVEMENT_DATA, 4*2+m_completedAchievements.size()*4*2+m_completedAchievements.size()*7*4); BuildAllDataPacket(&data); GetPlayer()->GetSession()->SendPacket(&data); } @@ -228,7 +228,7 @@ void AchievementMgr::SendAllAchievementData() 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_ALL_ACHIEVEMENT_DATA,4+4*2+m_completedAchievements.size()*4*2+m_completedAchievements.size()*7*4); + 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); @@ -245,6 +245,7 @@ void AchievementMgr::BuildAllDataPacket(WorldPacket *data) *data << uint32(secsToTimeBitFields(iter->second)); } *data << int32(-1); + for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) { *data << uint32(iter->first); @@ -255,6 +256,7 @@ void AchievementMgr::BuildAllDataPacket(WorldPacket *data) *data << uint32(0); *data << uint32(0); } + *data << int32(-1); } diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 68b5dce0b..24c2e37f1 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -40,6 +40,7 @@ #include "SpellAuras.h" #include "Pet.h" #include "SocialMgr.h" +#include "Tools.h" void WorldSession::HandleRepopRequestOpcode( WorldPacket & /*recv_data*/ ) { @@ -1850,3 +1851,18 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data ) _player->SetUInt64Value(UNIT_FIELD_CHARM, guid); _player->SetUInt64Value(PLAYER_FARSIGHT, guid); } + +void WorldSession::HandleInspectAchievements( WorldPacket & recv_data ) +{ + sLog.outString("WorldSession::HandleInspectAchievements"); + uint64 guid; + if(!readGUID(recv_data, guid)) + return; + + Player *player = objmgr.GetPlayer(guid); + if(!player) + return; + + player->GetAchievementMgr().SendRespondInspectAchievements(_player); +} + diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 7ccccdeeb..ce4c9d159 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -1157,7 +1157,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*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_NEVER, &WorldSession::Handle_NULL }, + /*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_NEVER, &WorldSession::Handle_NULL }, /*0x46E*/ { "CMSG_COMPLETE_ACHIEVEMENT_CHEAT", STATUS_NEVER, &WorldSession::Handle_NULL }, diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 58549d797..e63f87b58 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -654,6 +654,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleSpellClick(WorldPacket& recv_data); void HandleAlterAppearance(WorldPacket& recv_data); void HandleRemoveGlyph(WorldPacket& recv_data); + void HandleInspectAchievements(WorldPacket& recv_data); private: // private trade methods void moveItems(Item* myItems[], Item* hisItems[]); From c5dbf49ece25d5f81f0af8bd070b936f452fa6ba Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Thu, 30 Oct 2008 00:29:40 +0300 Subject: [PATCH 041/256] Fixed MSG_LIST_STABLED_PETS --- src/game/AuctionHouse.cpp | 14 ++++++++++++++ src/game/NPCHandler.cpp | 4 +--- src/game/Opcodes.h | 6 +++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/game/AuctionHouse.cpp b/src/game/AuctionHouse.cpp index ad122d524..b233ce466 100644 --- a/src/game/AuctionHouse.cpp +++ b/src/game/AuctionHouse.cpp @@ -750,4 +750,18 @@ 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/NPCHandler.cpp b/src/game/NPCHandler.cpp index bebf2770e..db5d9eb3d 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -517,8 +517,7 @@ void WorldSession::SendStablePet(uint64 guid ) data << uint32(pet->GetEntry()); data << uint32(pet->getLevel()); data << pet->GetName(); // petname - data << uint32(0); // was loyalty - data << uint8(0x01); // client slot 1 == current pet (0) + data << uint8(0x01); // flags?, client slot 1 == current pet (0) ++num; } @@ -535,7 +534,6 @@ void WorldSession::SendStablePet(uint64 guid ) data << uint32(fields[3].GetUInt32()); // creature entry data << uint32(fields[4].GetUInt32()); // level data << fields[5].GetString(); // name - data << uint32(0); // was loyalty data << uint8(fields[1].GetUInt32()+1); // slot ++num; diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 3ec8544e7..d7f09ab90 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1208,10 +1208,10 @@ enum Opcodes SMSG_PET_LEARNED_SPELL = 0x499, // uint16 spellid, Your pet learned spell: %s SMSG_PET_UNLEARNED_SPELL = 0x49A, // uint16 spellid, Your pet unlearned %s UMSG_UNKNOWN_1179 = 0x49B, // not found in client - CMSG_UNKNOWN_1180 = 0x49C, // lua: HearthAndResurrectFromArea + CMSG_UNKNOWN_1180 = 0x49C, // LUA: HearthAndResurrectFromArea SMSG_UNKNOWN_1181 = 0x49D, // empty - SMSG_UNKNOWN_1182 = 0x49E, // uint32 EVENT_CRITERIA_UPDATE - SMSG_UNKNOWN_1183 = 0x49F, // uint32 EVENT_ACHIEVEMENT_EARNED + SMSG_CRITERIA_REMOVE = 0x49E, // uint32, broadcasts EVENT_CRITERIA_UPDATE + SMSG_ACHIEVEMENT_REMOVE = 0x49F, // uint32, broadcasts EVENT_ACHIEVEMENT_EARNED UMSG_UNKNOWN_1184 = 0x4A0, // not found in client UMSG_UNKNOWN_1185 = 0x4A1, // not found in client UMSG_UNKNOWN_1186 = 0x4A2, // not found in client From 6b32fa717583ed33cb8f4187f151ae69ed5ed75a Mon Sep 17 00:00:00 2001 From: arrai Date: Thu, 30 Oct 2008 20:31:42 +0100 Subject: [PATCH 042/256] Added database support for achievement progress Implemented ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHIEVEMENT --- sql/wotlk_updates/6_character_achievement.sql | 14 +++ src/game/AchievementMgr.cpp | 117 ++++++++++++++---- src/game/AchievementMgr.h | 21 +++- src/game/CharacterHandler.cpp | 2 + src/game/Player.cpp | 2 +- src/game/Player.h | 4 +- 6 files changed, 134 insertions(+), 26 deletions(-) create mode 100644 sql/wotlk_updates/6_character_achievement.sql diff --git a/sql/wotlk_updates/6_character_achievement.sql b/sql/wotlk_updates/6_character_achievement.sql new file mode 100644 index 000000000..fed3a6c39 --- /dev/null +++ b/sql/wotlk_updates/6_character_achievement.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS `character_achievement` ( + `guid` int(11) NOT NULL, + `achievement` int(11) NOT NULL, + `date` int(11) NOT NULL, + PRIMARY KEY (`guid`,`achievement`) + ) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +CREATE TABLE IF NOT EXISTS `character_achievement_progress` ( + `guid` int(11) NOT NULL, + `criteria` int(11) NOT NULL, + `counter` int(11) NOT NULL, + `date` int(11) NOT NULL, + PRIMARY KEY (`guid`,`criteria`) + ) ENGINE=MyISAM DEFAULT CHARSET=latin1; diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index e4a82c638..dabd365c4 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -23,20 +23,76 @@ #include "Database/DBCEnums.h" #include "ObjectMgr.h" #include "Guild.h" +#include "Database/DatabaseEnv.h" AchievementMgr::AchievementMgr(Player *player) { m_player = player; } -void AchievementMgr::SaveToDB() +AchievementMgr::~AchievementMgr() { - // TODO store achievements + for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) + delete iter->second; + m_criteriaProgress.clear(); } -void AchievementMgr::LoadFromDB() +void AchievementMgr::SaveToDB() { - // TODO load achievements + if(!m_completedAchievements.empty()) + { + CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = %u", GetPlayer()->GetGUIDLow()); + + std::ostringstream ss; + ss << "INSERT INTO character_achievement (guid, achievement, date) VALUES "; + for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); iter++) + { + if(iter != m_completedAchievements.begin()) + ss << ", "; + ss << "("<GetGUIDLow() << ", " << iter->first << ", " << iter->second << ")"; + } + CharacterDatabase.Execute( ss.str().c_str() ); + } + + if(!m_criteriaProgress.empty()) + { + CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = %u", GetPlayer()->GetGUIDLow()); + + std::ostringstream ss; + ss << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES "; + for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) + { + if(iter != m_criteriaProgress.begin()) + ss << ", "; + ss << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second->counter << ", " << iter->second->date << ")"; + } + CharacterDatabase.Execute( ss.str().c_str() ); + } +} + +void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult) +{ + if(achievementResult) + { + do + { + Field *fields = achievementResult->Fetch(); + m_completedAchievements[fields[0].GetUInt32()] = fields[1].GetUInt32(); + } while(achievementResult->NextRow()); + delete achievementResult; + } + + if(criteriaResult) + { + do + { + Field *fields = criteriaResult->Fetch(); + CriteriaProgress *progress = new CriteriaProgress(fields[0].GetUInt32(), fields[1].GetUInt32(), fields[2].GetUInt64()); + m_criteriaProgress[progress->id] = progress; + } while(criteriaResult->NextRow()); + delete criteriaResult; + } + } void AchievementMgr::SendAchievementEarned(uint32 achievementId) @@ -79,18 +135,17 @@ void AchievementMgr::SendAchievementEarned(uint32 achievementId) GetPlayer()->SendMessageToSet(&data, true); } -void AchievementMgr::SendCriteriaUpdate(uint32 criteriaId, uint32 counter) +void AchievementMgr::SendCriteriaUpdate(CriteriaProgress *progress) { - sLog.outString("AchievementMgr::SendCriteriaUpdate(%u, %u)", criteriaId, counter); WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8); - data << uint32(criteriaId); + data << uint32(progress->id); // the counter is packed like a packed Guid - data.appendPackGUID(counter); + data.appendPackGUID(progress->counter); data.append(GetPlayer()->GetPackGUID()); data << uint32(0); - data << uint32(secsToTimeBitFields(time(NULL))); + data << uint32(secsToTimeBitFields(progress->date)); data << uint32(0); // timer 1 data << uint32(0); // timer 2 GetPlayer()->SendMessageToSet(&data, true); @@ -121,6 +176,9 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if(IsCompletedCriteria(achievementCriteria)) continue; + if(achievementCriteria->groupFlag & ACHIEVEMENT_CRITERIA_GROUP_NOT_IN_GROUP && GetPlayer()->GetGroup()) + continue; + switch (type) { case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: @@ -129,8 +187,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: SetCriteriaProgress(achievementCriteria, GetPlayer()->GetByteValue(PLAYER_BYTES_2, 2)+1); break; - default: - return; } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); @@ -146,15 +202,20 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER) return false; - if(m_criteriaProgress.find(achievementCriteria->ID) == m_criteriaProgress.end()) + CriteriaProgressMap::iterator itr = m_criteriaProgress.find(achievementCriteria->ID); + if(itr == m_criteriaProgress.end()) return false; + CriteriaProgress *progress = itr->second; + switch(achievementCriteria->requiredType) { case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL: - return m_criteriaProgress[achievementCriteria->ID] >= achievementCriteria->reach_level.level; + return progress->counter >= achievementCriteria->reach_level.level; case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT: - return m_criteriaProgress[achievementCriteria->ID] >= achievementCriteria->buy_bank_slot.numberOfSlots; + return progress->counter >= achievementCriteria->buy_bank_slot.numberOfSlots; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHIEVEMENT: + return m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end(); } return false; } @@ -189,7 +250,7 @@ AchievementCompletionState AchievementMgr::GetAchievementCompletionState(Achieve if(IsCompletedCriteria(criteria) && criteria->completionFlag & ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL) return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED; - // found an umcompleted criteria, but DONT return false - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL + // 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; } @@ -202,8 +263,21 @@ AchievementCompletionState AchievementMgr::GetAchievementCompletionState(Achieve void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue) { sLog.outString("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue); - m_criteriaProgress[entry->ID] = newValue; - SendCriteriaUpdate(entry->ID, newValue); + CriteriaProgress *progress = NULL; + + if(m_criteriaProgress.find(entry->ID) == m_criteriaProgress.end()) + { + progress = new CriteriaProgress(entry->ID, newValue); + m_criteriaProgress[entry->ID]=progress; + } + else + { + progress = m_criteriaProgress[entry->ID]; + if(progress->counter == newValue) + return; + progress->counter = newValue; + } + SendCriteriaUpdate(progress); } void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) @@ -214,6 +288,8 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) SendAchievementEarned(achievement->ID); m_completedAchievements[achievement->ID] = time(NULL); + + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHIEVEMENT); // TODO: reward titles and items } @@ -248,16 +324,15 @@ void AchievementMgr::BuildAllDataPacket(WorldPacket *data) for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) { - *data << uint32(iter->first); - data->appendPackGUID(iter->second); + *data << uint32(iter->second->id); + data->appendPackGUID(iter->second->counter); data->append(GetPlayer()->GetPackGUID()); *data << uint32(0); - *data << uint32(secsToTimeBitFields(time(NULL))); + *data << uint32(secsToTimeBitFields(iter->second->date)); *data << uint32(0); *data << uint32(0); } *data << int32(-1); - } diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index b03ba4dbf..a66d695a3 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -21,8 +21,22 @@ #include "Common.h" #include "Database/DBCEnums.h" #include "Database/DBCStores.h" +#include "Database/DatabaseEnv.h" -typedef HM_NAMESPACE::hash_map CriteriaProgressMap; +struct CriteriaProgress +{ + CriteriaProgress(uint32 id, uint32 counter, time_t date = time(NULL)) + { + this->id = id; + this->counter = counter; + this->date = date; + } + uint32 id; + uint32 counter; + time_t date; +}; + +typedef HM_NAMESPACE::hash_map CriteriaProgressMap; typedef HM_NAMESPACE::hash_map CompletedAchievementMap; class Player; @@ -39,8 +53,9 @@ class AchievementMgr { public: AchievementMgr(Player* pl); + ~AchievementMgr(); - void LoadFromDB(); + void LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult); void SaveToDB(); void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, uint32 time=0); void CheckAllAchievementCriteria(); @@ -51,7 +66,7 @@ class AchievementMgr private: void SendAchievementEarned(uint32 achievementId); - void SendCriteriaUpdate(uint32 criteriaId, uint32 counter); + void SendCriteriaUpdate(CriteriaProgress *progress); void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue); void CompletedCriteria(AchievementCriteriaEntry const* entry); void CompletedAchievement(AchievementEntry const* entry); diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index ace5be7c7..1645c467a 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -79,6 +79,8 @@ bool LoginQueryHolder::Initialize() res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid)); // 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_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; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 36907d21d..a8bed7442 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -14088,7 +14088,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadDeclinedNames(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES)); - m_achievementMgr.LoadFromDB(); + m_achievementMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS), holder->GetResult(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS)); m_achievementMgr.CheckAllAchievementCriteria(); return true; } diff --git a/src/game/Player.h b/src/game/Player.h index c94242cbb..09462b537 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -836,9 +836,11 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS = 15, PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16, PLAYER_LOGIN_QUERY_LOADGUILD = 17, + PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS = 18, + PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS = 19, + MAX_PLAYER_LOGIN_QUERY = 20 }; -#define MAX_PLAYER_LOGIN_QUERY 18 // Player summoning auto-decline time (in secs) #define MAX_PLAYER_SUMMON_DELAY (2*MINUTE) From 8a29415450e1ab39c9049c48fe4d63ab3c927a7a Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Thu, 30 Oct 2008 17:10:57 +0300 Subject: [PATCH 043/256] Added one more supported client build (9149) --- src/realmd/AuthCodes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/realmd/AuthCodes.h b/src/realmd/AuthCodes.h index 0641a7064..731214f5a 100644 --- a/src/realmd/AuthCodes.h +++ b/src/realmd/AuthCodes.h @@ -66,8 +66,8 @@ enum LoginResult // 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 and WoW:TBC 3.0.3 client build 9155... +// will only support WoW and WoW:TBC 3.0.3 client build 9149, 9155... -#define EXPECTED_MANGOS_CLIENT_BUILD {9155, 0} +#define EXPECTED_MANGOS_CLIENT_BUILD {9149, 9155, 0} #endif From 5ca92eddd74fa08cb61ec7845ea75aa27fa9383d Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Thu, 30 Oct 2008 23:00:34 +0300 Subject: [PATCH 044/256] Fixed MSG_CORPSE_QUERY for dungeons/raids, fixed SMSG_ATTACKERSTATEUPDATE --- src/game/Map.h | 11 ++++++++ src/game/ObjectMgr.cpp | 2 +- src/game/Opcodes.h | 2 +- src/game/Player.cpp | 4 +++ src/game/QueryHandler.cpp | 40 ++++++++++++++++++++++++------ src/game/Unit.cpp | 32 +++++++++++------------- src/game/Unit.h | 29 +++++++++++++++------- src/shared/Database/DBCStructure.h | 22 ++++++++-------- src/shared/Database/DBCfmt.cpp | 2 +- 9 files changed, 96 insertions(+), 48 deletions(-) diff --git a/src/game/Map.h b/src/game/Map.h index 6da1e56ae..e904a2ba5 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -219,6 +219,17 @@ class MANGOS_DLL_SPEC Map : public GridRefManager, public MaNGOS::Obj 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(); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index ffcaeaebf..a10777068 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -5020,7 +5020,7 @@ AreaTrigger const* ObjectMgr::GetGoBackTrigger(uint32 Map) const if(!mapEntry) return NULL; for (AreaTriggerMap::const_iterator itr = mAreaTriggers.begin(); itr != mAreaTriggers.end(); itr++) { - if(itr->second.target_mapId == mapEntry->parent_map) + if(itr->second.target_mapId == mapEntry->entrance_map) { AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(itr->first); if(atEntry && atEntry->mapid == Map) diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index d7f09ab90..969ead4ef 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1123,7 +1123,7 @@ enum Opcodes SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x444, SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x445, CMSG_CALENDAR_COMPLAIN = 0x446, - SMSG_CALENDAR_EVENT_RESERVED_2 = 0x447, + SMSG_CALENDAR_EVENT_RESERVED_2 = 0x447, // CMSG_CALENDAR_GET_CALENDAR in 9155 SMSG_CALENDAR_EVENT_RESERVED_3 = 0x448, CMSG_SAVE_DANCE = 0x449, SMSG_NOTIFY_DANCE = 0x44A, diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a8bed7442..b27297742 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3598,6 +3598,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?) diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp index 2f6380d17..232e72536 100644 --- a/src/game/QueryHandler.cpp +++ b/src/game/QueryHandler.cpp @@ -31,6 +31,7 @@ #include "NPCHandler.h" #include "ObjectAccessor.h" #include "Pet.h" +#include "MapManager.h" void WorldSession::SendNameQueryOpcode(Player *p) { @@ -272,19 +273,42 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) Corpse *corpse = GetPlayer()->GetCorpse(); - uint8 found = 1; - if(!corpse) - found = 0; + uint8 found = corpse ? 1 : 0; + + int32 mapid = corpse->GetMapId(); + float x = corpse->GetPositionX(); + float y = corpse->GetPositionY(); + float z = corpse->GetPositionZ(); + int32 corpsemapid = _player->GetMapId(); + + if(found) + { + if(Map *map = corpse->GetMap()) + { + 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+found*(5*4))); data << uint8(found); if(found) { - data << corpse->GetMapId(); - data << corpse->GetPositionX(); - data << corpse->GetPositionY(); - data << corpse->GetPositionZ(); - data << _player->GetMapId(); + data << int32(mapid); + data << float(x); + data << float(y); + data << float(z); + data << int32(corpsemapid); } SendPacket(&data); } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 53d713a27..9cc926dec 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -1791,9 +1791,7 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama case MELEE_HIT_BLOCK_CRIT: case MELEE_HIT_CRIT: { - //*hitInfo = 0xEA; - // 0xEA - *hitInfo = HITINFO_CRITICALHIT | HITINFO_NORMALSWING2 | 0x8; + *hitInfo = HITINFO_CRITICALHIT | HITINFO_NORMALSWING2 | HITINFO_UNK2; // Crit bonus calc uint32 crit_bonus; @@ -4377,11 +4375,11 @@ 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(0); // WotLK + data << uint32(Damage-AbsorbDamage-Resist-BlockedAmount);// damage + data << uint32(0); // overkill value data << (uint8)SwingType; // count? @@ -4391,17 +4389,17 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, data << (uint32)(Damage-AbsorbDamage-Resist-BlockedAmount); // end loop - if(HitInfo & (HITINFO_RESIST | HITINFO_ABSORB)) + if(HitInfo & (HITINFO_ABSORB | HITINFO_ABSORB2)) { // for(i = 0; i < SwingType; ++i) - data << (uint32)Resist; + data << uint32(AbsorbDamage); // end loop } - if(HitInfo & (HITINFO_CRITICALHIT | HITINFO_UNK2)) + if(HitInfo & (HITINFO_RESIST | HITINFO_RESIST2)) { // for(i = 0; i < SwingType; ++i) - data << uint32(0); // what is it? + data << uint32(Resist); // end loop } @@ -4409,17 +4407,17 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, data << (uint32)0; data << (uint32)0; + if(HitInfo & HITINFO_BLOCK) + { + data << uint32(BlockedAmount); + } + if(HitInfo & HITINFO_UNK3) { data << uint32(0); } - /*if(unknown & HitInfo) - { - data << uint32(0); - }*/ - - /*if(HitInfo & HITINFO_UNK1) + if(HitInfo & HITINFO_UNK1) { data << uint32(0); data << float(0); @@ -4436,7 +4434,7 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit *target, uint8 SwingType, data << float(0); } data << uint32(0); - }*/ + } SendMessageToSet( &data, true ); } diff --git a/src/game/Unit.h b/src/game/Unit.h index 44cc6e270..f8cb224dc 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -208,16 +208,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 atleast 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 diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index de3f80dfe..05d69075f 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -860,18 +860,18 @@ struct MailTemplateEntry struct MapEntry { - uint32 MapID; // 0 + uint32 MapID; // 0 //char* internalname; // 1 unused - uint32 map_type; // 2 + uint32 map_type; // 2 // 3 0 or 1 for battlegrounds (not arenas) - char* name[16]; // 4-19 + char* name[16]; // 4-19 // 20 name flags, unused - uint32 linked_zone; // 21 common zone for instance and continent map + 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 + uint32 multimap_id; // 56 // 57 //chat* unknownText1[16]; // 58-73 unknown empty text fields, possible normal Intro text. // 74 text flags @@ -879,14 +879,14 @@ struct MapEntry // 91 text flags //chat* unknownText2[16]; // 92-107 unknown empty text fields // 108 text flags - int32 parent_map; // 109 map_id of parent map - //float start_x // 110 enter x coordinate (if exist single entry) - //float start_y // 111 enter y coordinate (if exist single entry) - uint32 resetTimeRaid; // 112 - uint32 resetTimeHeroic; // 113 + 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) + uint32 addon; // 116 (0-original maps,1-tbc addon) // 117 some kind of time? // Helpers diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 46afd6b3c..1fbb324d9 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -58,7 +58,7 @@ const char ItemRandomSuffixfmt[]="nxxxxxxxxxxxxxxxxxxiiiiiiiiii"; const char ItemSetEntryfmt[]="dssssssssssssssssxxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii"; const char LockEntryfmt[]="niiiiiiiiiiiiiiiiiiiiiiiixxxxxxxx"; const char MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; -const char MapEntryfmt[]="nxixssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxiixxix"; +const char MapEntryfmt[]="nxixssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiffiixxix"; const char QuestSortEntryfmt[]="nxxxxxxxxxxxxxxxxx"; const char RandomPropertiesPointsfmt[]="niiiiiiiiiiiiiii"; const char ScalingStatDistributionfmt[]="niiiiiiiiiiiiiiiiiiiii"; From 6707038cfc2edacc22ea99786087e0a013a3c55b Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Fri, 31 Oct 2008 00:13:56 +0300 Subject: [PATCH 045/256] Crash fix --- src/game/QueryHandler.cpp | 46 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp index 232e72536..a3eeacdce 100644 --- a/src/game/QueryHandler.cpp +++ b/src/game/QueryHandler.cpp @@ -273,7 +273,13 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) Corpse *corpse = GetPlayer()->GetCorpse(); - uint8 found = corpse ? 1 : 0; + if(!corpse) + { + WorldPacket data(MSG_CORPSE_QUERY, 1); + data << uint8(0); // corpse not found + SendPacket(&data); + return; + } int32 mapid = corpse->GetMapId(); float x = corpse->GetPositionX(); @@ -281,35 +287,29 @@ void WorldSession::HandleCorpseQueryOpcode(WorldPacket & /*recv_data*/) float z = corpse->GetPositionZ(); int32 corpsemapid = _player->GetMapId(); - if(found) + if(Map *map = corpse->GetMap()) { - if(Map *map = corpse->GetMap()) + if(map->IsDungeon()) { - if(map->IsDungeon()) - { - if(!map->GetEntrancePos(mapid, x, y)) - return; + if(!map->GetEntrancePos(mapid, x, y)) + return; - Map *entrance_map = MapManager::Instance().GetMap(mapid, _player); - if(!entrance_map) - return; + Map *entrance_map = MapManager::Instance().GetMap(mapid, _player); + if(!entrance_map) + return; - z = entrance_map->GetHeight(x, y, MAX_HEIGHT); - corpsemapid = corpse->GetMapId(); - } + z = entrance_map->GetHeight(x, y, MAX_HEIGHT); + corpsemapid = corpse->GetMapId(); } } - WorldPacket data(MSG_CORPSE_QUERY, (1+found*(5*4))); - data << uint8(found); - if(found) - { - data << int32(mapid); - data << float(x); - data << float(y); - data << float(z); - data << int32(corpsemapid); - } + 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); } From 0d6805ec943b70fe9c036f966697297fc293d9cd Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 31 Oct 2008 12:35:08 +0100 Subject: [PATCH 046/256] Implemented ACHIEVEMENT_FLAG_REALM_FIRST_REACH --- src/game/AchievementMgr.cpp | 38 ++++++++++++++++++++++++++++-- src/game/AchievementMgr.h | 4 ++-- src/game/ObjectMgr.cpp | 16 +++++++++++++ src/game/ObjectMgr.h | 2 ++ src/game/World.cpp | 3 +++ src/shared/Database/DBCEnums.h | 8 +++++-- src/shared/Database/DBCStructure.h | 2 +- 7 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index dabd365c4..ee77c73a6 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -202,6 +202,13 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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(objmgr.allCompletedAchievements.find(achievement->ID)!=objmgr.allCompletedAchievements.end()) + return false; + } + CriteriaProgressMap::iterator itr = m_criteriaProgress.find(achievementCriteria->ID); if(itr == m_criteriaProgress.end()) return false; @@ -211,10 +218,32 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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_COMPLETE_ARCHIEVEMENT: + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: return m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end(); } return false; @@ -289,7 +318,12 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) SendAchievementEarned(achievement->ID); m_completedAchievements[achievement->ID] = time(NULL); - UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHIEVEMENT); + // 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)) + objmgr.allCompletedAchievements.insert(achievement->ID); + + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT); // TODO: reward titles and items } diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index a66d695a3..00429188a 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -38,6 +38,7 @@ struct CriteriaProgress typedef HM_NAMESPACE::hash_map CriteriaProgressMap; typedef HM_NAMESPACE::hash_map CompletedAchievementMap; +typedef std::set AchievementSet; class Player; class WorldPacket; @@ -61,7 +62,6 @@ class AchievementMgr void CheckAllAchievementCriteria(); void SendAllAchievementData(); void SendRespondInspectAchievements(Player* player); - Player* GetPlayer() { return m_player;} private: @@ -77,7 +77,7 @@ class AchievementMgr Player* m_player; CriteriaProgressMap m_criteriaProgress; CompletedAchievementMap m_completedAchievements; + }; - #endif diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index a10777068..e26f20b97 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -563,6 +563,22 @@ void ObjectMgr::LoadCreatureLocales() sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() ); } +void ObjectMgr::LoadCompletedAchievements() +{ + QueryResult *result = WorldDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); + + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + allCompletedAchievements.insert(fields[0].GetUInt32()); + } while(result->NextRow()); + + delete result; +} + void ObjectMgr::LoadNpcOptionLocales() { mNpcOptionLocaleMap.clear(); // need for reload case diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 2b7a83875..4c3a2950b 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -553,6 +553,7 @@ class ObjectMgr void LoadNpcTextId(); void LoadVendors(); void LoadTrainerSpell(); + void LoadCompletedAchievements(); std::string GeneratePetName(uint32 entry); uint32 GetBaseXP(uint32 level); @@ -757,6 +758,7 @@ class ObjectMgr bool IsVendorItemValid( uint32 vendor_entry, uint32 item, uint32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* pl = NULL, std::set* skip_vendors = NULL ) const; void LoadAchievementCriteriaList(); AchievementCriteriaEntryList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type); + std::set allCompletedAchievements; protected: uint32 m_auctionid; diff --git a/src/game/World.cpp b/src/game/World.cpp index fa789a661..7647abbff 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -931,6 +931,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading AchievementCriteriaList..." ); objmgr.LoadAchievementCriteriaList(); + sLog.outString( "Loading completed achievements..." ); + objmgr.LoadCompletedAchievements(); + sLog.outString( "Loading SkillLineAbilityMultiMap Data..." ); spellmgr.LoadSkillLineAbilityMap(); diff --git a/src/shared/Database/DBCEnums.h b/src/shared/Database/DBCEnums.h index 5b67af8aa..83cd83d40 100644 --- a/src/shared/Database/DBCEnums.h +++ b/src/shared/Database/DBCEnums.h @@ -34,7 +34,11 @@ enum AchievementFactionFlags enum AchievementFlags { - ACHIEVEMENT_FLAG_COUNTER = 0x00000001, + ACHIEVEMENT_FLAG_COUNTER = 0x00000001, + ACHIEVEMENT_FLAG_REACH_LEVEL = 0x00000004, + ACHIEVEMENT_FLAG_AVERAGE = 0x00000040, + ACHIEVEMENT_FLAG_REALM_FIRST_REACH= 0x00000100, + ACHIEVEMENT_FLAG_REALM_FIRST_KILL = 0x00000200, }; enum AchievementCriteriaCondition @@ -66,7 +70,7 @@ enum AchievementCriteriaTypes ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1, ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5, ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7, - ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHIEVEMENT = 8, + 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, diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 05d69075f..c98c87fb1 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -101,7 +101,7 @@ struct AchievementCriteriaEntry uint32 skillLevel; // 4 } reach_skill_level; - // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHIEVEMENT = 8 + // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8 struct { uint32 linkedAchievement; // 3 From d885ba7fe10fc6ba9fb810e75bda9718bf614461 Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 31 Oct 2008 14:42:33 +0100 Subject: [PATCH 047/256] Implemented ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE Implemented faction specific achievements --- src/game/AchievementMgr.cpp | 21 ++++++++++++++++++++- src/game/AchievementMgr.h | 2 +- src/game/Player.cpp | 1 + 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index ee77c73a6..7a3a6003a 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -179,6 +179,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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: @@ -187,6 +195,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); @@ -243,6 +258,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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 m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end(); } @@ -289,7 +306,7 @@ AchievementCompletionState AchievementMgr::GetAchievementCompletionState(Achieve return ACHIEVEMENT_COMPLETED_COMPLETED_NOT_STORED; } -void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue) +void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative) { sLog.outString("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue); CriteriaProgress *progress = NULL; @@ -302,6 +319,8 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, else { progress = m_criteriaProgress[entry->ID]; + if(relative) + newValue += progress->counter; if(progress->counter == newValue) return; progress->counter = newValue; diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index 00429188a..7e12b389f 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -67,7 +67,7 @@ class AchievementMgr private: void SendAchievementEarned(uint32 achievementId); void SendCriteriaUpdate(CriteriaProgress *progress); - void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue); + 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); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index b27297742..79c8bb348 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -13100,6 +13100,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); From a22b90177537576282fc296c641e048acb4aeda8 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Fri, 31 Oct 2008 19:06:41 +0300 Subject: [PATCH 048/256] go fix --- src/game/GameObject.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index b9fb5033a..874088db3 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -123,7 +123,16 @@ 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_PARENTROTATION, rotation0); + int64 rotation = 0; + float f_rot = sin(ang / 2.0f); + int64 i_rot = f_rot / atan(pow(2.0f, -20.0f)); + rotation |= (i_rot << 43 >> 43) & 0x00000000001FFFFF; + + sLog.outDebug("go_create: ang: %f, rot: " SI64FMTD, ang, rotation); + + SetUInt64Value(GAMEOBJECT_ROTATION, rotation); + + SetFloatValue(GAMEOBJECT_PARENTROTATION+0, rotation0); SetFloatValue(GAMEOBJECT_PARENTROTATION+1, rotation1); SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2); SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3); From 4baf9568531a9361219d80e46a35fffc84936e4e Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 31 Oct 2008 19:43:06 +0100 Subject: [PATCH 049/256] Implemented ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST and ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND --- src/game/AchievementMgr.cpp | 51 +++++++++++++++++++++++++++++++++++++ src/game/AchievementMgr.h | 1 - src/game/BattleGround.cpp | 1 + src/game/Player.cpp | 10 ++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 7a3a6003a..c24d7d043 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -202,6 +202,47 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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; + } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); @@ -262,6 +303,15 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve return progress->counter >= achievementCriteria->kill_creature.creatureCount; case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT: return m_completedAchievements.find(achievementCriteria->complete_achievement.linkedAchievement) != m_completedAchievements.end(); + case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL: + return progress->counter >= achievementCriteria->reach_skill_level.skillLevel; + 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_COMPLETE_BATTLEGROUND: + // just used as a counter - return false + return false; } return false; } @@ -281,6 +331,7 @@ void AchievementMgr::CompletedCriteria(AchievementCriteriaEntry const* criteria) } } +// TODO: achievement 705 requires 4 criteria to be fulfilled AchievementCompletionState AchievementMgr::GetAchievementCompletionState(AchievementEntry const* entry) { if(m_completedAchievements.find(entry->ID)!=m_completedAchievements.end()) diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index 7e12b389f..f34759f78 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -38,7 +38,6 @@ struct CriteriaProgress typedef HM_NAMESPACE::hash_map CriteriaProgressMap; typedef HM_NAMESPACE::hash_map CompletedAchievementMap; -typedef std::set AchievementSet; class Player; class WorldPacket; diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 1fd112bcd..838be2a47 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -406,6 +406,7 @@ void BattleGround::EndBattleGround(uint32 winner) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); plr->GetSession()->SendPacket(&data); + plr->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1); } if(Source) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 79c8bb348..3ec3f7b84 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -4582,6 +4582,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; } @@ -4706,6 +4707,7 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step) new_value = MaxValue; SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,MaxValue)); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL); sLog.outDebug("Player::UpdateSkillPro Chance=%3.1f%% taken", Chance/10.0); return true; } @@ -4885,7 +4887,10 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal) if(iIsDaily()) + { SetDailyQuestStatus(quest_id); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, 1); + } if ( !pQuest->IsRepeatable() ) SetQuestStatus(quest_id, QUEST_STATUS_COMPLETE); @@ -12438,6 +12447,7 @@ 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); } void Player::FailQuest( uint32 quest_id ) From be03894ec54232f9d95960b9ee86b8d4fb2546bd Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 31 Oct 2008 20:34:53 +0100 Subject: [PATCH 050/256] Implemented ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL Fixed typo in my previous commit --- src/game/AchievementMgr.cpp | 8 +++++++- src/game/Player.cpp | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index c24d7d043..9f331ba51 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -238,10 +238,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case if(!miscvalue1) continue; - if(GetPlayer()->GetMapID() != achievementCriteria->complete_battleground.mapID) + 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; } if(IsCompletedCriteria(achievementCriteria)) @@ -312,6 +316,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: // just used as a counter - return false return false; + case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL: + return progress->counter >= 1; } return false; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 3ec3f7b84..06e2a9089 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2773,6 +2773,9 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, } } + if(!loading) + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL); + // return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell return active && !disabled && !superceded_old; } From 38892c864f3c12bd82406c412290d70ca7aed264 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Fri, 31 Oct 2008 23:37:32 +0300 Subject: [PATCH 051/256] Updated THANKS file --- THANKS | 3 +++ src/game/GameObject.cpp | 15 +++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/THANKS b/THANKS index 5d5e8fded..46ed80e44 100644 --- a/THANKS +++ b/THANKS @@ -21,6 +21,9 @@ similar to this one: community with a great server. We have not gained too much help from them, but we have recieved some. + Thanks to WCell team (especially Ralek) for reseach on realm reconnect sequence, + item scaling stats algorithm, gameobject rotation issues. + The easiest policy with this file is to thank everyone who contributes to the project, without judging the value of the contribution. diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 874088db3..795a95988 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -124,11 +124,18 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float SetFloatValue(GAMEOBJECT_FACING, ang); //this is not facing angle int64 rotation = 0; - float f_rot = sin(ang / 2.0f); - int64 i_rot = f_rot / atan(pow(2.0f, -20.0f)); - rotation |= (i_rot << 43 >> 43) & 0x00000000001FFFFF; - sLog.outDebug("go_create: ang: %f, rot: " SI64FMTD, ang, rotation); + 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); From 5d79048e68638cfd304ef517c322c9e4ba119752 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 1 Nov 2008 08:42:49 +0300 Subject: [PATCH 052/256] No real changes --- src/game/Level2.cpp | 1 - src/game/QueryHandler.cpp | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 453dfdcea..9174b921e 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -4202,7 +4202,6 @@ bool ChatHandler::HandleNpcTameCommand(const char* args) // set pet to defensive mode by default (some classes can't control contolled pets in fact). pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE); - // prepare visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1); diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp index e35a0d14e..12fc3a8a3 100644 --- a/src/game/QueryHandler.cpp +++ b/src/game/QueryHandler.cpp @@ -97,7 +97,7 @@ void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult *result, uint32 else field = fields[2].GetUInt32(); - // guess size + // guess size WorldPacket data( SMSG_NAME_QUERY_RESPONSE, (8+1+4+4+4+10) ); data << MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER); data << name; @@ -180,7 +180,7 @@ void WorldSession::HandleCreatureQueryOpcode( WorldPacket & recv_data ) data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty data << SubName; data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0 - data << (uint32)ci->type_flags; // flags wdbFeild7=wad flags1 + data << (uint32)ci->type_flags; // flags wdbFeild7=wad flags1 data << (uint32)ci->type; data << (uint32)ci->family; // family wdbFeild9 data << (uint32)ci->rank; // rank wdbFeild10 From a2ed2319474a2aff551f516536a93eb6fd81b238 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 1 Nov 2008 17:38:32 +0300 Subject: [PATCH 053/256] Compile fix --- src/game/GossipDef.cpp | 8 +------- src/game/Level2.cpp | 8 +++++--- src/game/QuestDef.h | 32 ++++++++++++++++---------------- src/game/Unit.cpp | 2 +- 4 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index d1e66f9d7..36a83a84e 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -135,12 +135,6 @@ void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ) GossipMenuItem const& gItem = mGossipMenu.GetItem(iI); data << uint32( iI ); data << uint8( gItem.m_gIcon ); - // icons: - // 0 unlearn talents/misc - // 1 trader - // 2 taxi - // 3 trainer - // 9 BG/arena data << uint8( gItem.m_gCoded ); // makes pop up box password data << uint32(gItem.m_gBoxMoney); // money required to open menu, 2.0.3 data << gItem.m_gMessage; // text for gossip item @@ -155,7 +149,7 @@ void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ) uint32 questID = qItem.m_qId; Quest const* pQuest = objmgr.GetQuestTemplate(questID); - data << questID; + data << uint32(questID); data << uint32( qItem.m_qIcon ); data << uint32( pQuest ? pQuest->GetQuestLevel() : 0 ); std::string Title = pQuest->GetTitle(); diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 9174b921e..b1f613520 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -4199,17 +4199,19 @@ bool ChatHandler::HandleNpcTameCommand(const char* args) 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 contolled pets in fact). + // set pet to defensive mode by default (some classes can't control controlled pets in fact). pet->GetCharmInfo()->SetReactState(REACT_DEFENSIVE); + uint32 level = (creatureTarget->getLevel() < (player->getLevel() - 5)) ? (player->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 MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet); // visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()); + pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); // caster have pet now player->SetPet(pet); diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h index 551c3dd5f..316209393 100644 --- a/src/game/QuestDef.h +++ b/src/game/QuestDef.h @@ -112,24 +112,24 @@ enum __QuestGiverStatus enum __QuestFlags { - // Flags used at server and sended to client - QUEST_FLAGS_STAY_ALIVE = 1, // Not used currently - QUEST_FLAGS_PARTY_ACCEPT = 2, // Not used currently. If player in party, all players that can accept this quest will receive confirmation box to accept quest CMSG_QUEST_CONFIRM_ACCEPT/SMSG_QUEST_CONFIRM_ACCEPT - QUEST_FLAGS_EXPLORATION = 4, // Not used currently - QUEST_FLAGS_SHARABLE = 8, // Can be shared: Player::CanShareQuest() - //QUEST_FLAGS_NONE2 = 16, // Not used currently - QUEST_FLAGS_EPIC = 32, // Not used currently: Unsure of content - QUEST_FLAGS_RAID = 64, // Not used currently - QUEST_FLAGS_TBC = 128, // Not used currently: Available if TBC expension enabled only - QUEST_FLAGS_UNK2 = 256, // Not used currently: _DELIVER_MORE Quest needs more than normal _q-item_ drops from mobs - QUEST_FLAGS_HIDDEN_REWARDS = 512, // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE)) - QUEST_FLAGS_AUTO_REWARDED = 1024, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side. - QUEST_FLAGS_TBC_RACES = 2048, // Not used currently: Bloodelf/draenei starting zone quests - QUEST_FLAGS_DAILY = 4096, // Used to know quest is Daily one + // Flags used at server and sent to client + QUEST_FLAGS_STAY_ALIVE = 0x00000001, // Not used currently + QUEST_FLAGS_PARTY_ACCEPT = 0x00000002, // Not used currently. If player in party, all players that can accept this quest will receive confirmation box to accept quest CMSG_QUEST_CONFIRM_ACCEPT/SMSG_QUEST_CONFIRM_ACCEPT + QUEST_FLAGS_EXPLORATION = 0x00000004, // Not used currently + QUEST_FLAGS_SHARABLE = 0x00000008, // Can be shared: Player::CanShareQuest() + //QUEST_FLAGS_NONE2 = 0x00000010, // Not used currently + QUEST_FLAGS_EPIC = 0x00000020, // Not used currently: Unsure of content + QUEST_FLAGS_RAID = 0x00000040, // Not used currently + QUEST_FLAGS_TBC = 0x00000080, // Not used currently: Available if TBC expension enabled only + QUEST_FLAGS_UNK2 = 0x00000100, // Not used currently: _DELIVER_MORE Quest needs more than normal _q-item_ drops from mobs + QUEST_FLAGS_HIDDEN_REWARDS = 0x00000200, // Items and money rewarded only sent in SMSG_QUESTGIVER_OFFER_REWARD (not in SMSG_QUESTGIVER_QUEST_DETAILS or in client quest log(SMSG_QUEST_QUERY_RESPONSE)) + QUEST_FLAGS_AUTO_REWARDED = 0x00000400, // These quests are automatically rewarded on quest complete and they will never appear in quest log client side. + QUEST_FLAGS_TBC_RACES = 0x00000800, // Not used currently: Blood elf/Draenei starting zone quests + QUEST_FLAGS_DAILY = 0x00001000, // Used to know quest is Daily one // Mangos flags for set SpecialFlags in DB if required but used only at server QUEST_MANGOS_FLAGS_REPEATABLE = 0x010000, // Set by 1 in SpecialFlags from DB - QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT = 0x020000, // Set by 2 in SpecialFlags from DB (if reequired area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script DLL) + QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT = 0x020000, // Set by 2 in SpecialFlags from DB (if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script DLL) QUEST_MANGOS_FLAGS_DB_ALLOWED = 0xFFFF | QUEST_MANGOS_FLAGS_REPEATABLE | QUEST_MANGOS_FLAGS_EXPLORATION_OR_EVENT, // Mangos flags for internal use only @@ -318,7 +318,7 @@ struct QuestStatusData : m_status(QUEST_STATUS_NONE),m_rewarded(false), m_explored(false), m_timer(0), uState(QUEST_NEW) { - memset(m_itemcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint32)); + memset(m_itemcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint32)); memset(m_creatureOrGOcount, 0, QUEST_OBJECTIVES_COUNT * sizeof(uint32)); } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 0ac6e726f..26ae65eb8 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -10879,7 +10879,7 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,this->getFaction()); pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, spell_id); - uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel(); + uint32 level = (creatureTarget->getLevel() < (getLevel() - 5)) ? (getLevel() - 5) : creatureTarget->getLevel(); pet->SetFreeTalentPoints(pet->GetMaxTalentPointsForLevel(level)); if(!pet->InitStatsForLevel(level)) From f4c3430088560280bc8a880517313ef3d451c76e Mon Sep 17 00:00:00 2001 From: arrai Date: Sat, 1 Nov 2008 22:54:55 +0100 Subject: [PATCH 054/256] Implemented ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE and ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP --- src/game/AchievementMgr.cpp | 60 +++++++++++++++++++++++++++++++++--- src/game/MovementHandler.cpp | 3 ++ src/game/Player.cpp | 2 ++ src/game/Unit.cpp | 9 ++++++ 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 9f331ba51..bf65393a4 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -24,6 +24,7 @@ #include "ObjectMgr.h" #include "Guild.h" #include "Database/DatabaseEnv.h" +#include "GameEvent.h" AchievementMgr::AchievementMgr(Player *player) { @@ -246,7 +247,50 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if(GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID)) 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 falltime, calculate to fall height format given in dbc + uint32 fallHeight = uint32(0.06f*miscvalue1-91.5)*100; + SetCriteriaProgress(achievementCriteria, fallHeight); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: + if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID)) + SetCriteriaProgress(achievementCriteria, 1); + break; } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); @@ -313,11 +357,19 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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_COMPLETE_BATTLEGROUND: - // just used as a counter - return false - return false; 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; + + // 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; } diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index a2ec545f0..d1cf3a9ed 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -322,6 +322,9 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) damage = target->GetMaxHealth()/2; target->EnvironmentalDamage(target->GetGUID(), DAMAGE_FALL, damage); + + if(target->isAlive()) + target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, movementInfo.fallTime); } //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 1f5a6865b..cb6a895cf 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1250,6 +1250,7 @@ void Player::setDeathState(DeathState s) // passive spell if(!ressSpellId) ressSpellId = GetResurrectionSpellId(); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, 1); } Unit::setDeathState(s); @@ -12451,6 +12452,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* 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 ) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 26ae65eb8..5860d8261 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -690,6 +690,15 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa 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) From bea468bbc358c01ed6871909178d410392d20d4c Mon Sep 17 00:00:00 2001 From: arrai Date: Sun, 2 Nov 2008 15:48:14 +0100 Subject: [PATCH 055/256] Implemented SMSG_SERVER_FIRST_ACHIEVEMENT Implemented removing entries from achievement tables at player deletion --- src/game/AchievementMgr.cpp | 52 +++++++++++++++++++++++-------------- src/game/AchievementMgr.h | 2 +- src/game/Player.cpp | 2 ++ 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index bf65393a4..3cb56dc7e 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -25,6 +25,7 @@ #include "Guild.h" #include "Database/DatabaseEnv.h" #include "GameEvent.h" +#include "World.h" AchievementMgr::AchievementMgr(Player *player) { @@ -96,26 +97,15 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri } -void AchievementMgr::SendAchievementEarned(uint32 achievementId) +void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) { - sLog.outString("AchievementMgr::SendAchievementEarned(%u)", achievementId); + sLog.outString("AchievementMgr::SendAchievementEarned(%u)", achievement->ID); - 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()); const char *msg = "|Hplayer:$N|h[$N]|h has earned the achievement $a!"; - data << uint32(strlen(msg)+1); - data << msg; - data << uint8(0); - data << uint32(achievementId); - GetPlayer()->SendMessageToSet(&data, true); - if(Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId())) { - data.Initialize(SMSG_MESSAGECHAT, 200); + WorldPacket data(SMSG_MESSAGECHAT, 200); + data << uint8(CHAT_MSG_ACHIEVEMENT); data << uint8(CHAT_MSG_GUILD_ACHIEVEMENT); data << uint32(LANG_UNIVERSAL); data << uint64(GetPlayer()->GetGUID()); @@ -124,13 +114,37 @@ void AchievementMgr::SendAchievementEarned(uint32 achievementId) data << uint32(strlen(msg)+1); data << msg; data << uint8(0); - data << uint32(achievementId); + 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); - data.Initialize(SMSG_ACHIEVEMENT_EARNED, 8+4+8); + } + WorldPacket data(SMSG_ACHIEVEMENT_EARNED, 8+4+8); data.append(GetPlayer()->GetPackGUID()); - data << uint32(achievementId); + data << uint32(achievement->ID); data << uint32(secsToTimeBitFields(time(NULL))); data << uint32(0); GetPlayer()->SendMessageToSet(&data, true); @@ -443,7 +457,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) if(achievement->flags & ACHIEVEMENT_FLAG_COUNTER || m_completedAchievements.find(achievement->ID)!=m_completedAchievements.end()) return; - SendAchievementEarned(achievement->ID); + SendAchievementEarned(achievement); m_completedAchievements[achievement->ID] = time(NULL); // don't insert for ACHIEVEMENT_FLAG_REALM_FIRST_KILL since otherwise only the first group member would reach that achievement diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index f34759f78..4a86277d6 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -64,7 +64,7 @@ class AchievementMgr Player* GetPlayer() { return m_player;} private: - void SendAchievementEarned(uint32 achievementId); + void SendAchievementEarned(AchievementEntry const* achievement); void SendCriteriaUpdate(CriteriaProgress *progress); void SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 newValue, bool relative=false); void CompletedCriteria(AchievementCriteriaEntry const* entry); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index cb6a895cf..52aa1ae7b 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3572,6 +3572,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); From 99ff9ab5d96386848bd2af1b44a95162971d0cd6 Mon Sep 17 00:00:00 2001 From: arrai Date: Sun, 2 Nov 2008 20:36:48 +0100 Subject: [PATCH 056/256] Fixed mixing up character and world database --- src/game/ObjectMgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index fa5547208..356deb8b9 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -565,7 +565,7 @@ void ObjectMgr::LoadCreatureLocales() void ObjectMgr::LoadCompletedAchievements() { - QueryResult *result = WorldDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); + QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); if(!result) return; From aaddf4b51bb80f89fcd45152d3410dabc0580a29 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 1 Nov 2008 21:08:39 +0300 Subject: [PATCH 057/256] Avoid access to bag item prototype for getting bag size, use related item update field instead as more fast source. --- src/game/Bag.cpp | 61 ++++------- src/game/Bag.h | 1 + src/game/Level2.cpp | 6 +- src/game/Player.cpp | 240 +++++++++++++++-------------------------- src/game/debugcmds.cpp | 6 +- 5 files changed, 112 insertions(+), 202 deletions(-) diff --git a/src/game/Bag.cpp b/src/game/Bag.cpp index 6345ff4d5..cd6c4d69a 100644 --- a/src/game/Bag.cpp +++ b/src/game/Bag.cpp @@ -37,30 +37,25 @@ Bag::Bag( ): Item() Bag::~Bag() { - for(int i = 0; iAddToWorld(); - } } void Bag::RemoveFromWorld() { - for(int i = 0; iRemoveFromWorld(); - } Item::RemoveFromWorld(); } @@ -109,7 +104,7 @@ bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result) return false; // cleanup bag content related item value fields (its will be filled correctly from `character_inventory`) - for (uint32 i = 0; i < GetProto()->ContainerSlots; i++) + for (int i = 0; i < MAX_BAG_SIZE; ++i) { SetUInt64Value(CONTAINER_FIELD_SLOT_1 + (i*2), 0); if (m_bagslot[i]) @@ -125,21 +120,16 @@ bool Bag::LoadFromDB(uint32 guid, uint64 owner_guid, QueryResult *result) void Bag::DeleteFromDB() { for (int i = 0; i < MAX_BAG_SIZE; i++) - { if (m_bagslot[i]) - { m_bagslot[i]->DeleteFromDB(); - } - } Item::DeleteFromDB(); } uint32 Bag::GetFreeSlots() const { - uint32 ContainerSlots=GetProto()->ContainerSlots; uint32 slots = 0; - for (uint8 i=0; i BuildCreateUpdateBlockForPlayer( data, target ); - } } // If the bag is empty returns true bool Bag::IsEmpty() const { - uint32 ContainerSlots=GetProto()->ContainerSlots; - for(uint32 i=0; i < ContainerSlots; i++) - if (m_bagslot[i]) return false; + for(uint32 i = 0; i < GetBagSize(); ++i) + if (m_bagslot[i]) + return false; return true; } uint32 Bag::GetItemCount( uint32 item, Item* eItem ) const { - uint32 ContainerSlots=GetProto()->ContainerSlots; - Item *pItem; uint32 count = 0; - for(uint32 i=0; i < ContainerSlots; i++) + for(uint32 i=0; i < GetBagSize(); ++i) { pItem = m_bagslot[i]; if( pItem && pItem != eItem && pItem->GetEntry() == item ) @@ -208,7 +194,7 @@ uint32 Bag::GetItemCount( uint32 item, Item* eItem ) const if(eItem && eItem->GetProto()->GemProperties) { - for(uint32 i=0; i < ContainerSlots; i++) + for(uint32 i=0; i < GetBagSize(); ++i) { pItem = m_bagslot[i]; if( pItem && pItem != eItem && pItem->GetProto()->Socket[0].Color ) @@ -221,29 +207,18 @@ uint32 Bag::GetItemCount( uint32 item, Item* eItem ) const uint8 Bag::GetSlotByItemGUID(uint64 guid) const { - uint32 ContainerSlots=GetProto()->ContainerSlots; - - for(uint32 i=0;iGetGUID() == guid) return i; - } + return NULL_SLOT; } -// Adds an item to a bag slot -// - slot can be NULL_SLOT, in that case function searchs for a free slot -// - Return values: 0 - item not added -// 1 - item added to a free slot (and perhaps to a stack) -// 2 - item added to a stack (item should be deleted) Item* Bag::GetItemByPos( uint8 slot ) const { - ItemPrototype const *pBagProto = GetProto(); - if( pBagProto ) - { - if( slot < pBagProto->ContainerSlots ) - return m_bagslot[slot]; - } + if( slot < GetBagSize() ) + return m_bagslot[slot]; + return NULL; } diff --git a/src/game/Bag.h b/src/game/Bag.h index 07ae17341..21458546e 100644 --- a/src/game/Bag.h +++ b/src/game/Bag.h @@ -50,6 +50,7 @@ class Bag : public Item uint8 GetSlotByItemGUID(uint64 guid) const; bool IsEmpty() const; uint32 GetFreeSlots() const; + uint32 GetBagSize() const { return GetUInt32Value(CONTAINER_FIELD_NUM_SLOTS); } // DB operations // overwrite virtual Item::SaveToDB diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index b1f613520..7ffe2bcae 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -859,12 +859,12 @@ bool ChatHandler::HandleItemMoveCommand(const char* args) srcslot = (uint8)atoi(pParam1); dstslot = (uint8)atoi(pParam2); - uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); - uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); - if(srcslot==dstslot) return true; + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); + uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); + m_session->GetPlayer()->SwapItem( src, dst ); return true; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 52aa1ae7b..96d0464cd 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -3859,10 +3859,9 @@ void Player::DurabilityLossAll(double percent, bool inventory) for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) - if(ItemPrototype const *pBagProto = pBag->GetProto()) - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - if(Item* pItem = GetItemByPos( i, j )) - DurabilityLoss(pItem,percent); + for(uint32 j = 0; j < pBag->GetBagSize(); j++) + if(Item* pItem = GetItemByPos( i, j )) + DurabilityLoss(pItem,percent); } } @@ -3904,10 +3903,9 @@ void Player::DurabilityPointsLossAll(int32 points, bool inventory) for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) - if(ItemPrototype const *pBagProto = pBag->GetProto()) - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - if(Item* pItem = GetItemByPos( i, j )) - DurabilityPointsLoss(pItem,points); + for(uint32 j = 0; j < pBag->GetBagSize(); j++) + if(Item* pItem = GetItemByPos( i, j )) + DurabilityPointsLoss(pItem,points); } } @@ -8074,24 +8072,19 @@ uint8 Player::CanUnequipItems( uint32 item, uint32 count ) const } } Bag *pBag; - ItemPrototype const *pBagProto; for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + pItem = GetItemByPos( i, j ); + if( pItem && pItem->GetEntry() == item ) { - pItem = GetItemByPos( i, j ); - if( pItem && pItem->GetEntry() == item ) - { - tempcount += pItem->GetCount(); - if( tempcount >= count ) - return EQUIP_ERR_OK; - } + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return EQUIP_ERR_OK; } } } @@ -8182,15 +8175,11 @@ Item* Player::GetItemByGuid( uint64 guid ) const Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - ItemPrototype const *pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - { - Item* pItem = pBag->GetItemByPos( j ); - if( pItem && pItem->GetGUID() == guid ) - return pItem; - } + Item* pItem = pBag->GetItemByPos( j ); + if( pItem && pItem->GetGUID() == guid ) + return pItem; } } } @@ -8199,15 +8188,11 @@ Item* Player::GetItemByGuid( uint64 guid ) const Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - ItemPrototype const *pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - { - Item* pItem = pBag->GetItemByPos( j ); - if( pItem && pItem->GetGUID() == guid ) - return pItem; - } + Item* pItem = pBag->GetItemByPos( j ); + if( pItem && pItem->GetGUID() == guid ) + return pItem; } } } @@ -8365,17 +8350,14 @@ bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const { if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) { - if(ItemPrototype const *pBagProto = pBag->GetProto()) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + Item* pItem = GetItemByPos( i, j ); + if( pItem && pItem->GetEntry() == item ) { - Item* pItem = GetItemByPos( i, j ); - if( pItem && pItem->GetEntry() == item ) - { - tempcount += pItem->GetCount(); - if( tempcount >= count ) - return true; - } + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return true; } } } @@ -8397,17 +8379,14 @@ bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const { if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) { - if(ItemPrototype const *pBagProto = pBag->GetProto()) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + Item* pItem = GetItemByPos( i, j ); + if( pItem && pItem->GetEntry() == item ) { - Item* pItem = GetItemByPos( i, j ); - if( pItem && pItem->GetEntry() == item ) - { - tempcount += pItem->GetCount(); - if( tempcount >= count ) - return true; - } + tempcount += pItem->GetCount(); + if( tempcount >= count ) + return true; } } } @@ -8485,22 +8464,15 @@ bool Player::HasItemTotemCategory( uint32 TotemCategory ) const if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) return true; } - Bag *pBag; - ItemPrototype const *pBagProto; for(uint8 i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; ++i) { - pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); - if( pBag ) + if(Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) { - pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); ++j) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; ++j) - { - pItem = GetItemByPos( i, j ); - if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) - return true; - } + pItem = GetItemByPos( i, j ); + if( pItem && IsTotemCategoryCompatiableWith(pItem->GetProto()->TotemCategory,TotemCategory )) + return true; } } } @@ -8606,7 +8578,7 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy if( !ItemCanGoIntoBag(pProto,pBagProto) ) return EQUIP_ERR_ITEM_DOESNT_GO_INTO_BAG; - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { // skip specific slot already processed in first called _CanStoreItem_InSpecificSlot if(j==skip_slot) @@ -9269,23 +9241,14 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { - Bag *pBag; - ItemPrototype const *pBagProto; - - pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); - if( pBag ) + if(Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) { - pBagProto = pBag->GetProto(); - - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + pItem2 = GetItemByPos( i, j ); + if (pItem2 && !pItem2->IsInTrade()) { - pItem2 = GetItemByPos( i, j ); - if (pItem2 && !pItem2->IsInTrade()) - { - inv_bags[i-INVENTORY_SLOT_BAG_START][j] = pItem2->GetCount(); - } + inv_bags[i-INVENTORY_SLOT_BAG_START][j] = pItem2->GetCount(); } } } @@ -9388,18 +9351,14 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t ); if( pBag ) { - pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + pItem2 = GetItemByPos( t, j ); + if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->Stackable ) { - pItem2 = GetItemByPos( t, j ); - if( pItem2 && pItem2->GetEntry() == pItem->GetEntry() && inv_bags[t-INVENTORY_SLOT_BAG_START][j] + pItem->GetCount() <= pProto->Stackable ) - { - inv_bags[t-INVENTORY_SLOT_BAG_START][j] += pItem->GetCount(); - b_found = true; - break; - } + inv_bags[t-INVENTORY_SLOT_BAG_START][j] += pItem->GetCount(); + b_found = true; + break; } } } @@ -9483,7 +9442,7 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const if( pBagProto && (pBagProto->Class != ITEM_CLASS_CONTAINER || pBagProto->SubClass != ITEM_SUBCLASS_CONTAINER) && ItemCanGoIntoBag(pProto,pBagProto) ) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { if( inv_bags[t-INVENTORY_SLOT_BAG_START][j] == 0 ) { @@ -9517,17 +9476,13 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, t ); if( pBag ) { - pBagProto = pBag->GetProto(); - if( pBagProto && ItemCanGoIntoBag(pProto,pBagProto)) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + if( inv_bags[t-INVENTORY_SLOT_BAG_START][j] == 0 ) { - if( inv_bags[t-INVENTORY_SLOT_BAG_START][j] == 0 ) - { - inv_bags[t-INVENTORY_SLOT_BAG_START][j] = 1; - b_found = true; - break; - } + inv_bags[t-INVENTORY_SLOT_BAG_START][j] = 1; + b_found = true; + break; } } } @@ -10620,40 +10575,33 @@ void Player::DestroyItemCount( uint32 item, uint32 count, bool update, bool uneq } // in inventory bags - Bag *pBag; - ItemPrototype const *pBagProto; for(int i = INVENTORY_SLOT_BAG_START; i < INVENTORY_SLOT_BAG_END; i++) { - pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); - if( pBag ) + if(Bag *pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i )) { - pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) + pItem = pBag->GetItemByPos(j); + if( pItem && pItem->GetEntry() == item ) { - pItem = pBag->GetItemByPos(j); - if( pItem && pItem->GetEntry() == item ) + // all items in bags can be unequipped + if( pItem->GetCount() + remcount <= count ) { - // all items in bags can be unequipped - if( pItem->GetCount() + remcount <= count ) - { - remcount += pItem->GetCount(); - DestroyItem( i, j, update ); + remcount += pItem->GetCount(); + DestroyItem( i, j, update ); - if(remcount >=count) - return; - } - else - { - pProto = pItem->GetProto(); - ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount ); - pItem->SetCount( pItem->GetCount() - count + remcount ); - if( IsInWorld() && update ) - pItem->SendUpdateToPlayer( this ); - pItem->SetState(ITEM_CHANGED, this); + if(remcount >=count) return; - } + } + else + { + pProto = pItem->GetProto(); + ItemRemovedQuestCheck( pItem->GetEntry(), count - remcount ); + pItem->SetCount( pItem->GetCount() - count + remcount ); + if( IsInWorld() && update ) + pItem->SendUpdateToPlayer( this ); + pItem->SetState(ITEM_CHANGED, this); + return; } } } @@ -10715,15 +10663,11 @@ void Player::DestroyZoneLimitedItem( bool update, uint32 new_zone ) Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - ItemPrototype const *pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - { - Item* pItem = pBag->GetItemByPos(j); - if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) - DestroyItem( i, j, update); - } + Item* pItem = pBag->GetItemByPos(j); + if( pItem && pItem->IsLimitedToAnotherMapOrZone(GetMapId(),new_zone) ) + DestroyItem( i, j, update); } } } @@ -10759,17 +10703,13 @@ void Player::DestroyConjuredItems( bool update ) Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - ItemPrototype const *pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - { - Item* pItem = pBag->GetItemByPos(j); - if( pItem && pItem->GetProto() && - (pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) && - (pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) ) - DestroyItem( i, j, update); - } + Item* pItem = pBag->GetItemByPos(j); + if( pItem && pItem->GetProto() && + (pItem->GetProto()->Class == ITEM_CLASS_CONSUMABLE) && + (pItem->GetProto()->Flags & ITEM_FLAGS_CONJURED) ) + DestroyItem( i, j, update); } } } @@ -11417,15 +11357,11 @@ void Player::RemoveAllEnchantments(EnchantmentSlot slot) Bag* pBag = (Bag*)GetItemByPos( INVENTORY_SLOT_BAG_0, i ); if( pBag ) { - ItemPrototype const *pBagProto = pBag->GetProto(); - if( pBagProto ) + for(uint32 j = 0; j < pBag->GetBagSize(); j++) { - for(uint32 j = 0; j < pBagProto->ContainerSlots; j++) - { - Item* pItem = pBag->GetItemByPos(j); - if( pItem && pItem->GetEnchantmentId(slot) ) - pItem->ClearEnchantment(slot); - } + Item* pItem = pBag->GetItemByPos(j); + if( pItem && pItem->GetEnchantmentId(slot) ) + pItem->ClearEnchantment(slot); } } } diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index 1fd67d6a0..60c225376 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -324,8 +324,7 @@ bool ChatHandler::HandleGetItemState(const char* args) else { Bag *bag = (Bag*)item; - const ItemPrototype *proto = bag->GetProto(); - for (uint8 j = 0; j < proto->ContainerSlots; ++j) + for (uint8 j = 0; j < bag->GetBagSize(); ++j) { Item* item = bag->GetItemByPos(j); if (item && item->GetState() == state) @@ -421,8 +420,7 @@ bool ChatHandler::HandleGetItemState(const char* args) if(item->IsBag()) { Bag *bag = (Bag*)item; - const ItemPrototype *proto = bag->GetProto(); - for (uint8 j = 0; j < proto->ContainerSlots; ++j) + for (uint8 j = 0; j < bag->GetBagSize(); ++j) { Item* item = bag->GetItemByPos(j); if (!item) continue; From e4a2d43a47aadf62e38771fa46ecb58950b5c55c Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 1 Nov 2008 21:18:36 +0300 Subject: [PATCH 058/256] Better check client inventory pos data received in some client packets to skip invalid cases. --- src/game/ItemHandler.cpp | 42 +++++++++++++++++++++++ src/game/Level2.cpp | 6 ++++ src/game/Player.cpp | 72 ++++++++++++++++++++++++++++++++++++++++ src/game/Player.h | 2 ++ 4 files changed, 122 insertions(+) diff --git a/src/game/ItemHandler.cpp b/src/game/ItemHandler.cpp index 3a6083b0d..f76e4ad2e 100644 --- a/src/game/ItemHandler.cpp +++ b/src/game/ItemHandler.cpp @@ -47,6 +47,18 @@ void WorldSession::HandleSplitItemOpcode( WorldPacket & recv_data ) if (count==0) return; //check count - if zero it's fake packet + if(!_player->IsValidPos(srcbag,srcslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + if(!_player->IsValidPos(dstbag,dstslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + _player->SplitItem( src, dst, count ); } @@ -64,6 +76,18 @@ void WorldSession::HandleSwapInvItemOpcode( WorldPacket & recv_data ) if(srcslot==dstslot) return; + if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + if(!_player->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + uint16 src = ( (INVENTORY_SLOT_BAG_0 << 8) | srcslot ); uint16 dst = ( (INVENTORY_SLOT_BAG_0 << 8) | dstslot ); @@ -107,6 +131,18 @@ void WorldSession::HandleSwapItem( WorldPacket & recv_data ) if(src==dst) return; + if(!_player->IsValidPos(srcbag,srcslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + if(!_player->IsValidPos(dstbag,dstslot)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + _player->SwapItem( src, dst ); } @@ -751,6 +787,12 @@ void WorldSession::HandleAutoStoreBagItemOpcode( WorldPacket & recv_data ) if( !pItem ) return; + if(!_player->IsValidPos(dstbag,NULL_SLOT)) + { + _player->SendEquipError( EQUIP_ERR_ITEM_DOESNT_GO_TO_SLOT, NULL, NULL ); + return; + } + uint16 src = pItem->GetPos(); // check unequip potability for equipped items and bank bags diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 7ffe2bcae..e120e3fca 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -862,6 +862,12 @@ bool ChatHandler::HandleItemMoveCommand(const char* args) if(srcslot==dstslot) return true; + if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,srcslot)) + return false; + + if(!m_session->GetPlayer()->IsValidPos(INVENTORY_SLOT_BAG_0,dstslot)) + return false; + uint16 src = ((INVENTORY_SLOT_BAG_0 << 8) | srcslot); uint16 dst = ((INVENTORY_SLOT_BAG_0 << 8) | dstslot); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 96d0464cd..324573aba 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -8323,6 +8323,78 @@ bool Player::IsBagPos( uint16 pos ) return false; } +bool Player::IsValidPos( uint8 bag, uint8 slot ) +{ + // post selected + if(bag == NULL_BAG) + return true; + + if (bag == INVENTORY_SLOT_BAG_0) + { + // any post selected + if (slot == NULL_SLOT) + return true; + + // equipment + if (slot < EQUIPMENT_SLOT_END) + return true; + + // bag equip slots + if (slot >= INVENTORY_SLOT_BAG_START && slot < INVENTORY_SLOT_BAG_END) + return true; + + // backpack slots + if (slot >= INVENTORY_SLOT_ITEM_START && slot < INVENTORY_SLOT_ITEM_END) + return true; + + // keyring slots + if (slot >= KEYRING_SLOT_START && slot < KEYRING_SLOT_END) + return true; + + // bank main slots + if (slot >= BANK_SLOT_ITEM_START && slot < BANK_SLOT_ITEM_END) + return true; + + // bank bag slots + if (slot >= BANK_SLOT_BAG_START && slot < BANK_SLOT_BAG_END) + return true; + + return false; + } + + // bag content slots + if (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END) + { + Bag* pBag = (Bag*)GetItemByPos (INVENTORY_SLOT_BAG_0, bag); + if(!pBag) + return false; + + // any post selected + if (slot == NULL_SLOT) + return true; + + return slot < pBag->GetBagSize(); + } + + // bank bag content slots + if( bag >= BANK_SLOT_BAG_START && bag < BANK_SLOT_BAG_END ) + { + Bag* pBag = (Bag*)GetItemByPos (INVENTORY_SLOT_BAG_0, bag); + if(!pBag) + return false; + + // any post selected + if (slot == NULL_SLOT) + return true; + + return slot < pBag->GetBagSize(); + } + + // where this? + return false; +} + + bool Player::HasItemCount( uint32 item, uint32 count, bool inBankAlso ) const { uint32 tempcount = 0; diff --git a/src/game/Player.h b/src/game/Player.h index 09462b537..50b464293 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1063,6 +1063,8 @@ class MANGOS_DLL_SPEC Player : public Unit static bool IsBagPos( uint16 pos ); static bool IsBankPos( uint16 pos ) { return IsBankPos(pos >> 8,pos & 255); } static bool IsBankPos( uint8 bag, uint8 slot ); + bool IsValidPos( uint16 pos ) { return IsBankPos(pos >> 8,pos & 255); } + bool IsValidPos( uint8 bag, uint8 slot ); bool HasBankBagSlot( uint8 slot ) const; bool HasItemCount( uint32 item, uint32 count, bool inBankAlso = false ) const; bool HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item const* ignoreItem = NULL); From 3f5d1903a57c06e07e5897f9a73f3d1eb9af355a Mon Sep 17 00:00:00 2001 From: derex Date: Sat, 1 Nov 2008 21:21:12 +0200 Subject: [PATCH 059/256] Restore build on FreeBSD. --- dep/ACE_wrappers/ace/OS_NS_netdb.inl | 10 +++++----- dep/ACE_wrappers/ace/os_include/os_signal.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/dep/ACE_wrappers/ace/OS_NS_netdb.inl b/dep/ACE_wrappers/ace/OS_NS_netdb.inl index f1d0009ee..58ebc0c1f 100644 --- a/dep/ACE_wrappers/ace/OS_NS_netdb.inl +++ b/dep/ACE_wrappers/ace/OS_NS_netdb.inl @@ -125,7 +125,7 @@ ACE_OS::gethostbyaddr_r (const char *addr, *h_errnop = h_errno; return (struct hostent *) 0; } -# elif defined (__GLIBC__) +# elif defined (__GLIBC__) || defined (__FreeBSD__) // GNU C library has a different signature ACE_OS::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA)); @@ -318,7 +318,7 @@ ACE_OS::gethostbyname_r (const char *name, *h_errnop = h_errno; return (struct hostent *) 0; } -# elif defined (__GLIBC__) +# elif defined (__GLIBC__) || defined (__FreeBSD__) // GNU C library has a different signature ACE_OS::memset (buffer, 0, sizeof (ACE_HOSTENT_DATA)); @@ -528,7 +528,7 @@ ACE_OS::getprotobyname_r (const char *name, else return 0; //FUZZ: enable check_for_lack_ACE_OS -# elif defined (__GLIBC__) +# elif defined (__GLIBC__) || defined (__FreeBSD__) // GNU C library has a different signature //FUZZ: disable check_for_lack_ACE_OS if (::getprotobyname_r (name, @@ -609,7 +609,7 @@ ACE_OS::getprotobynumber_r (int proto, //FUZZ: enable check_for_lack_ACE_OS else return 0; -# elif defined (__GLIBC__) +# elif defined (__GLIBC__) || defined (__FreeBSD__) // GNU C library has a different signature //FUZZ: disable check_for_lack_ACE_OS if (::getprotobynumber_r (proto, @@ -695,7 +695,7 @@ ACE_OS::getservbyname_r (const char *svc, //FUZZ: enable check_for_lack_ACE_OS else return (struct servent *) 0; -# elif defined (__GLIBC__) +# elif defined (__GLIBC__) || defined (__FreeBSD__) // GNU C library has a different signature ACE_OS::memset (buf, 0, sizeof (ACE_SERVENT_DATA)); diff --git a/dep/ACE_wrappers/ace/os_include/os_signal.h b/dep/ACE_wrappers/ace/os_include/os_signal.h index fdfd21e99..957450601 100644 --- a/dep/ACE_wrappers/ace/os_include/os_signal.h +++ b/dep/ACE_wrappers/ace/os_include/os_signal.h @@ -25,6 +25,7 @@ #endif /* ACE_LACKS_PRAGMA_ONCE */ #include "ace/os_include/sys/os_types.h" +#include "ace/os_include/os_pthread.h" #if !defined (ACE_LACKS_SIGNAL_H) extern "C" { From b62f376d736590900477c557c5844e585525f641 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 1 Nov 2008 08:42:49 +0300 Subject: [PATCH 060/256] No real changes (cherry picked from commit 80e8f17627db58b3d275407547687aec6d10362b) --- src/game/Level2.cpp | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index e120e3fca..2a872f378 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -1799,13 +1799,30 @@ bool ChatHandler::HandlePInfoCommand(const char* args) // get additional information from DB else { + // 0 + QueryResult *result = CharacterDatabase.PQuery("SELECT totaltime FROM characters WHERE guid = '%u'", GUID_LOPART(targetGUID)); + if (!result) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + Field *fields = result->Fetch(); + total_player_time = fields[0].GetUInt32(); + delete result; + + Tokens data; + if (!Player::LoadValuesArrayFromDB(data,targetGUID)) + { + SendSysMessage(LANG_PLAYER_NOT_FOUND); + SetSentErrorMessage(true); + return false; + } + + money = Player::GetUInt32ValueFromArray(data, PLAYER_FIELD_COINAGE); + level = Player::GetUInt32ValueFromArray(data, UNIT_FIELD_LEVEL); + accId = objmgr.GetPlayerAccountIdByGUID(targetGUID); - WorldSession session(0,NULL,SEC_PLAYER,0,0,LOCALE_enUS); - Player plr(&session); // use fake session for temporary load - plr.MinimalLoadFromDB(NULL, targetGUID); - money = plr.GetMoney(); - total_player_time = plr.GetTotalPlayedTime(); - level = plr.getLevel(); } std::string username = GetMangosString(LANG_ERROR); @@ -2861,12 +2878,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) std::string show = show_str; uint32 Maxpoint; - sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u", lowguid); - - sLog.outDebug("DEBUG: HandleWpShowCommand: Habe creature: %ld", target ); - - sLog.outDebug("DEBUG: HandleWpShowCommand: wpshow - show: %s", show_str); - //PSendSysMessage("wpshow - show: %s", show); + sLog.outDebug("DEBUG: HandleWpShowCommand: lowguid: %u show: %s", lowguid, show_str); // Show info for the selected waypoint if(show == "info") @@ -2887,7 +2899,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) QueryResult *result = WorldDatabase.PQuery( "SELECT id, point, waittime, emote, spell, text1, text2, text3, text4, text5, model1, model2 FROM creature_movement WHERE wpguid = %u", - target->GetGUID() ); + target->GetGUIDLow() ); if(!result) { // Since we compare float values, we have to deal with @@ -3387,7 +3399,7 @@ bool ChatHandler::HandleWpImportCommand(const char *args) { getline (infile,line); //cout << line << endl; - QueryResult *result = WorldDatabase.PQuery(line.c_str()); + QueryResult *result = WorldDatabase.Query(line.c_str()); delete result; } infile.close(); From 004bdf1d3c931ff0b4624b13ead82b2111f04a63 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 1 Nov 2008 23:53:35 +0300 Subject: [PATCH 061/256] Fixed some format arg type/value pairs. Other warnings. --- src/game/BattleGround.cpp | 4 ++-- src/game/BattleGroundBE.cpp | 2 +- src/game/BattleGroundEY.cpp | 5 +++-- src/game/BattleGroundMgr.cpp | 2 +- src/game/BattleGroundRL.cpp | 2 +- src/game/BattleGroundWS.cpp | 2 +- src/game/CharacterHandler.cpp | 3 ++- src/game/Corpse.cpp | 6 ++++-- src/game/LootMgr.cpp | 3 ++- src/game/MiscHandler.cpp | 4 ++-- src/game/MotionMaster.cpp | 1 + src/game/NPCHandler.cpp | 5 +++-- src/game/Pet.cpp | 8 +++++--- src/shared/Database/SqlOperations.cpp | 3 ++- 14 files changed, 30 insertions(+), 20 deletions(-) diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 838be2a47..c1a622e7e 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -998,7 +998,7 @@ bool BattleGround::DelCreature(uint32 type) Creature *cr = HashMapHolder::Find(m_BgCreatures[type]); if(!cr) { - sLog.outError("Can't find creature guid: %u",m_BgCreatures[type]); + sLog.outError("Can't find creature guid: %u",GUID_LOPART(m_BgCreatures[type])); return false; } cr->CleanupsBeforeDelete(); @@ -1012,7 +1012,7 @@ bool BattleGround::DelObject(uint32 type) GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); if(!obj) { - sLog.outError("Can't find gobject guid: %u",m_BgObjects[type]); + sLog.outError("Can't find gobject guid: %u",GUID_LOPART(m_BgObjects[type])); return false; } obj->SetRespawnTime(0); // not save respawn time diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index dcf994325..4ad71988e 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -104,7 +104,7 @@ void BattleGroundBE::AddPlayer(Player *plr) m_PlayerScores[plr->GetGUID()] = sc; } -void BattleGroundBE::RemovePlayer(Player *plr, uint64 guid) +void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) { } diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 165b1cf42..5eb6d6286 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -556,7 +556,7 @@ void BattleGroundEY::RespawnFlagAfterDrop() if(obj) obj->Delete(); else - sLog.outError("BattleGroundEY: Unknown dropped flag guid: %u",GetDroppedFlagGUID()); + sLog.outError("BattleGroundEY: Unknown dropped flag guid: %u",GUID_LOPART(GetDroppedFlagGUID())); SetDroppedFlagGUID(0); } @@ -741,7 +741,8 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) WorldSafeLocsEntry const *sg = NULL; sg = sWorldSafeLocsStore.LookupEntry(m_CapturingPointTypes[Point].GraveYardId); if(!sg || !AddSpiritGuide(Point, sg->x, sg->y, sg->z, 3.124139f, Team)) - sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: u, graveyard_id: %u", Point, Team, m_CapturingPointTypes[Point].GraveYardId); + sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: %u, graveyard_id: %u", + Point, Team, m_CapturingPointTypes[Point].GraveYardId); UpdatePointsIcons(Team, Point); UpdatePointsCount(Team); diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 8ef50bea9..c07639b8d 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -341,7 +341,7 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id) /*** BATTLEGROUND QUEUE EVENTS ***/ /*********************************************************/ -bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 p_time) +bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) { Player* plr = objmgr.GetPlayer( m_PlayerGuid ); diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index 130f46a63..4be135c70 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -98,7 +98,7 @@ void BattleGroundRL::AddPlayer(Player *plr) m_PlayerScores[plr->GetGUID()] = sc; } -void BattleGroundRL::RemovePlayer(Player *plr, uint64 guid) +void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) { } diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index c482a959e..4334304d6 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -198,7 +198,7 @@ void BattleGroundWS::RespawnFlagAfterDrop(uint32 team) if(obj) obj->Delete(); else - sLog.outError("unknown droped flag bg, guid: %u",GetDroppedFlagGUID(team)); + sLog.outError("unknown droped flag bg, guid: %u",GUID_LOPART(GetDroppedFlagGUID(team))); SetDroppedFlagGUID(0,team); } diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index f8ccbfa88..286b94553 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -758,7 +758,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) SendNotification(LANG_GM_ON); std::string IP_str = GetRemoteAddress(); - sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)",GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUID()); + sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)", + GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUIDLow()); m_playerLoading = false; delete holder; diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp index 6b298791d..c2a873a1b 100644 --- a/src/game/Corpse.cpp +++ b/src/game/Corpse.cpp @@ -79,7 +79,8 @@ bool Corpse::Create( uint32 guidlow, Player *owner, uint32 mapid, float x, float if(!IsPositionValid()) { - sLog.outError("ERROR: Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %d Y: ^%d)",guidlow,owner->GetName(),x,y); + sLog.outError("ERROR: Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + guidlow,owner->GetName(),x,y); return false; } @@ -196,7 +197,8 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields) if(!IsPositionValid()) { - sLog.outError("ERROR: Corpse (guidlow %d, owner %d) not created. Suggested coordinates isn't valid (X: %d Y: ^%d)",GetGUIDLow(),GUID_LOPART(GetOwnerGUID()),GetPositionX(),GetPositionY()); + sLog.outError("ERROR: Corpse (guidlow %d, owner %d) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + GetGUIDLow(),GUID_LOPART(GetOwnerGUID()),GetPositionX(),GetPositionY()); return false; } diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index c19535ccd..b88169161 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -268,7 +268,8 @@ bool LootStoreItem::IsValid(LootStore const& store, uint32 entry) const if( chance != 0 && chance < 0.000001f ) // loot with low chance { - sLog.outErrorDb("Table '%s' entry %d item %d: low chance (%d) - skipped", store.GetName(), entry, itemid, chance); + sLog.outErrorDb("Table '%s' entry %d item %d: low chance (%f) - skipped", + store.GetName(), entry, itemid, chance); return false; } } diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 24c2e37f1..9deb8582e 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -133,7 +133,7 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) wstrToLower(str[i]); - sLog.outDebug("String %u: %s", i, str[i].c_str()); + sLog.outDebug("String %u: %s", i, temp.c_str()); } std::wstring wplayer_name; @@ -969,7 +969,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket & recv_data) (fabs(rotateDy) > atEntry->box_y/2 + delta) || (fabs(dz) > atEntry->box_z/2 + delta) ) { - sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %u 1/2 box Z: %u rotate dX: %f rotate dY: %f dZ:%f), ignore Area Trigger ID: %u", + sLog.outDebug("Player '%s' (GUID: %u) too far (1/2 box X: %f 1/2 box Y: %f 1/2 box Z: %f rotate dX: %f rotate dY: %f dZ:%f), ignore Area Trigger ID: %u", pl->GetName(), pl->GetGUIDLow(), atEntry->box_x/2, atEntry->box_y/2, atEntry->box_z/2, rotateDx, rotateDy, dz, Trigger_ID); return; } diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index 0ebb40cd6..2dc42cd4d 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -186,6 +186,7 @@ MotionMaster::MoveChase(Unit* target, float dist, float angle) if(i_owner->GetTypeId()==TYPEID_PLAYER) { DEBUG_LOG("Player (GUID: %u) chase to %s (GUID: %u)", + i_owner->GetGUIDLow(), target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", target->GetTypeId()==TYPEID_PLAYER ? i_owner->GetGUIDLow() : ((Creature*)i_owner)->GetDBTableGUIDLow() ); Mutate(new TargetedMovementGenerator(*target,dist,angle)); diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index db5d9eb3d..8a5a2b244 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -137,14 +137,15 @@ void WorldSession::SendTrainerList( uint64 guid,std::string strTitle ) if (!ci) { - sLog.outDebug( "WORLD: SendTrainerList - (%u) NO CREATUREINFO! (GUID: %u)", uint32(GUID_LOPART(guid)), guid ); + sLog.outDebug( "WORLD: SendTrainerList - (GUID: %u) NO CREATUREINFO!",GUID_LOPART(guid) ); return; } TrainerSpellData const* trainer_spells = unit->GetTrainerSpells(); if(!trainer_spells) { - sLog.outDebug( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", guid, unit->GetEntry()); + sLog.outDebug( "WORLD: SendTrainerList - Training spells not found for creature (GUID: %u Entry: %u)", + GUID_LOPART(guid), unit->GetEntry()); return; } diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 2bc5f1b20..9c16b2fca 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -161,7 +161,8 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu if(!IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %d Y: ^%d)", GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)", + GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); delete result; return false; } @@ -179,7 +180,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu 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); @@ -734,7 +735,8 @@ bool Pet::CreateBaseAtCreature(Creature* creature) if(!IsPositionValid()) { - sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %d Y: ^%d)", GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); + sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %f Y: %f)", + GetGUIDLow(), GetEntry(), GetPositionX(), GetPositionY()); return false; } diff --git a/src/shared/Database/SqlOperations.cpp b/src/shared/Database/SqlOperations.cpp index 0993551cb..bc75c591e 100644 --- a/src/shared/Database/SqlOperations.cpp +++ b/src/shared/Database/SqlOperations.cpp @@ -100,7 +100,8 @@ bool SqlQueryHolder::SetQuery(size_t index, const char *sql) if(m_queries[index].first != NULL) { - sLog.outError("Attempt assign query to holder index (%u) where other query stored (Old: [%s] New: [%s])",index,m_queries.size(),m_queries[index].first,sql); + sLog.outError("Attempt assign query to holder index (%u) where other query stored (Old: [%s] New: [%s])", + index,m_queries[index].first,sql); return false; } From 79cb95999155d523c07366d49a2e5a655b3d4061 Mon Sep 17 00:00:00 2001 From: hunuza Date: Sun, 2 Nov 2008 15:58:24 +0100 Subject: [PATCH 062/256] Removed some unnecessary database queries. Removed unnecessary database queries in some command handlers. Replaced them with access to cached data or queries for only the needed data. Move database access in gossip select code to less often called place. --- src/game/Creature.cpp | 14 ++++---- src/game/Level3.cpp | 81 ++++++++++++++++++++++--------------------- 2 files changed, 50 insertions(+), 45 deletions(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index b208db2ad..aa9a27154 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -821,18 +821,20 @@ void Creature::OnGossipSelect(Player* player, uint32 option) return; } - uint32 textid=GetGossipTextId( action, zoneid); - if(textid==0) - textid=GetNpcTextId(); - switch (gossip->Action) { case GOSSIP_OPTION_GOSSIP: + { + uint32 textid = GetGossipTextId(action, zoneid); + if (textid == 0) + textid=GetNpcTextId(); + player->PlayerTalkClass->CloseGossip(); - player->PlayerTalkClass->SendTalking( textid ); + player->PlayerTalkClass->SendTalking(textid); break; + } case GOSSIP_OPTION_SPIRITHEALER: - if( player->isDead() ) + if (player->isDead()) CastSpell(this,17251,true,NULL,NULL,player->GetGUID()); break; case GOSSIP_OPTION_QUESTGIVER: diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index ebe54342c..0f13a89b1 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -1988,9 +1988,39 @@ bool ChatHandler::HandleAddItemSetCommand(const char* args) sLog.outDetail(GetMangosString(LANG_ADDITEMSET), itemsetId); - QueryResult *result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE itemset = %u",itemsetId); + bool found = false; + for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) + { + ItemPrototype const *pProto = sItemStorage.LookupEntry(id); + if (!pProto) + continue; - if(!result) + if (pProto->ItemSet == itemsetId) + { + found = true; + ItemPosCountVec dest; + uint8 msg = plTarget->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, pProto->ItemId, 1 ); + if (msg == EQUIP_ERR_OK) + { + Item* item = plTarget->StoreNewItem( dest, pProto->ItemId, true); + + // remove binding (let GM give it to another player later) + if (pl==plTarget) + item->SetBinding( false ); + + pl->SendNewItem(item,1,false,true); + if (pl!=plTarget) + plTarget->SendNewItem(item,1,true,false); + } + else + { + pl->SendEquipError( msg, NULL, NULL ); + PSendSysMessage(LANG_ITEM_CANNOT_CREATE, pProto->ItemId, 1); + } + } + } + + if (!found) { PSendSysMessage(LANG_NO_ITEMS_FROM_ITEMSET_FOUND,itemsetId); @@ -1998,35 +2028,6 @@ bool ChatHandler::HandleAddItemSetCommand(const char* args) return false; } - do - { - Field *fields = result->Fetch(); - uint32 itemId = fields[0].GetUInt32(); - - ItemPosCountVec dest; - uint8 msg = plTarget->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, itemId, 1 ); - if( msg == EQUIP_ERR_OK ) - { - Item* item = plTarget->StoreNewItem( dest, itemId, true); - - // remove binding (let GM give it to another player later) - if(pl==plTarget) - item->SetBinding( false ); - - pl->SendNewItem(item,1,false,true); - if(pl!=plTarget) - plTarget->SendNewItem(item,1,true,false); - } - else - { - pl->SendEquipError( msg, NULL, NULL ); - PSendSysMessage(LANG_ITEM_CANNOT_CREATE, itemId, 1); - } - - }while( result->NextRow() ); - - delete result; - return true; } @@ -4680,16 +4681,18 @@ bool ChatHandler::HandleAddQuest(const char* args) } // check item starting quest (it can work incorrectly if added without item in inventory) - QueryResult *result = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE startquest = '%u' LIMIT 1",entry); - if(result) + for (uint32 id = 0; id < sItemStorage.MaxEntry; id++) { - Field* fields = result->Fetch(); - uint32 item_id = fields[0].GetUInt32(); - delete result; + ItemPrototype const *pProto = sItemStorage.LookupEntry(id); + if (!pProto) + continue; - PSendSysMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry,item_id); - SetSentErrorMessage(true); - return false; + if (pProto->StartQuest == entry) + { + PSendSysMessage(LANG_COMMAND_QUEST_STARTFROMITEM, entry, pProto->ItemId); + SetSentErrorMessage(true); + return false; + } } // ok, normal (creature/GO starting) quest From 8d541034560db0b71aea996bfab50bb7f83da42d Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 2 Nov 2008 19:31:16 +0300 Subject: [PATCH 063/256] Fixed spell.dbc structure --- contrib/extractor/ad.exe | Bin 167936 -> 160768 bytes src/game/GameObject.cpp | 2 +- src/game/ObjectMgr.cpp | 2 +- src/game/Player.cpp | 2 +- src/game/SharedDefines.h | 16 +++++------ src/game/Spell.cpp | 4 +-- src/game/SpellAuras.cpp | 8 +++--- src/game/SpellEffects.cpp | 18 ++++++------ src/game/SpellMgr.cpp | 44 ++++++++++++++--------------- src/game/SpellMgr.h | 4 +-- src/game/Unit.cpp | 14 ++++----- src/shared/Database/DBCStructure.h | 30 ++++++++++---------- src/shared/Database/DBCfmt.cpp | 2 +- 13 files changed, 73 insertions(+), 73 deletions(-) diff --git a/contrib/extractor/ad.exe b/contrib/extractor/ad.exe index e9606e8e0eb6c359622315eccfc671674d28af96..eec43be65dd74dbc0a1f1749a05323faf9944a3b 100755 GIT binary patch delta 84892 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 delta 81592 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 { SetGoState(0); - SetUInt32Value(GAMEOBJECT_FLAGS, 32); + SetUInt32Value(GAMEOBJECT_FLAGS, GO_FLAG_NODESPAWN); UpdateData udata; WorldPacket packet; diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 356deb8b9..03b4e7042 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -6514,7 +6514,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; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 324573aba..bcc975f19 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18141,7 +18141,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()) { diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 5f1037d37..7e9b81eb5 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -775,7 +775,7 @@ enum SpellImmunity IMMUNITY_MECHANIC = 5 // enum Mechanics }; -#define MAX_SPELL_IMMUNITY 6 +#define MAX_SPELL_IMMUNITY 6 enum Targets { @@ -913,13 +913,13 @@ enum GameobjectTypes enum GameObjectFlags { - GO_FLAG_IN_USE = 0x01, //disables interaction while animated - GO_FLAG_LOCKED = 0x02, //require key, spell, event, etc to be opened. Makes "Locked" appear in tooltip - GO_FLAG_INTERACT_COND = 0x04, //cannot interact (condition to interact) - GO_FLAG_TRANSPORT = 0x08, //any kind of transport? Object can transport (elevator, boat, car) - GO_FLAG_UNK1 = 0x10, // - GO_FLAG_NODESPAWN = 0x20, //never despawn, typically for doors, they just change state - GO_FLAG_TRIGGERED = 0x40, //typically, summoned objects. Triggered by spell or other events + GO_FLAG_IN_USE = 0x00000001, //disables interaction while animated + GO_FLAG_LOCKED = 0x00000002, //require key, spell, event, etc to be opened. Makes "Locked" appear in tooltip + GO_FLAG_INTERACT_COND = 0x00000004, //cannot interact (condition to interact) + GO_FLAG_TRANSPORT = 0x00000008, //any kind of transport? Object can transport (elevator, boat, car) + GO_FLAG_UNK1 = 0x00000010, // + GO_FLAG_NODESPAWN = 0x00000020, //never despawn, typically for doors, they just change state + GO_FLAG_TRIGGERED = 0x00000040 //typically, summoned objects. Triggered by spell or other events }; enum TextEmotes diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index bb27bbd55..0dcab744f 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1550,7 +1550,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - bool inFront = m_spellInfo->SpellVisual != 3879; + bool inFront = m_spellInfo->SpellVisual[0] != 3879; MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE); TypeContainerVisitor world_object_notifier(notifier); @@ -3551,7 +3551,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; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index e76997017..6b1536855 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -4066,7 +4066,7 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) case SPELLFAMILY_ROGUE: { // Deadly poison aura state - if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual==5100) + if((m_spellProto->SpellFamilyFlags & 0x10000) && m_spellProto->SpellVisual[0]==5100) { if(apply) m_target->ModifyAuraState(AURA_STATE_DEADLY_POISON,true); @@ -4078,7 +4078,7 @@ void Aura::HandlePeriodicDamage(bool apply, bool Real) 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) + if(itr_spell && itr_spell->SpellFamilyName==SPELLFAMILY_ROGUE && (itr_spell->SpellFamilyFlags & 0x10000) && itr_spell->SpellVisual[0]==5100) { found = true; break; @@ -5765,7 +5765,7 @@ 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 @@ -5810,7 +5810,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) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 5c4c02e1b..2ef1da977 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -386,7 +386,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) case SPELLFAMILY_DRUID: { // Ferocious Bite - if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual==6587) + if((m_spellInfo->SpellFamilyFlags & 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]; @@ -466,7 +466,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) { // Deadly poison (only attacker applied) if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) && - (*itr)->GetSpellProto()->SpellVisual==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() ) + (*itr)->GetSpellProto()->SpellVisual[0]==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() ) { --combo; ++doses; @@ -504,7 +504,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) case SPELLFAMILY_HUNTER: { // Mongoose Bite - if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual==342) + if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342) { damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2); } @@ -1191,7 +1191,7 @@ 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); @@ -3838,13 +3838,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 @@ -4177,7 +4177,7 @@ void Spell::EffectWeaponDmg(uint32 i) spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized); } // Devastate bonus and sunder armor refresh - else if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508) + else if(m_spellInfo->SpellVisual[0] == 671 && m_spellInfo->SpellIconID == 1508) { customBonusDamagePercentMod = true; bonusDamagePercentMod = 0.0f; // only applied if auras found @@ -4186,7 +4186,7 @@ void Spell::EffectWeaponDmg(uint32 i) for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr) { SpellEntry const *proto = (*itr)->GetSpellProto(); - if(proto->SpellVisual == 406 && proto->SpellIconID == 565) + if(proto->SpellVisual[0] == 406 && proto->SpellIconID == 565) { int32 duration = GetSpellDuration(proto); (*itr)->SetAuraDuration(duration); diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index d0c4b8d9a..6fac0888f 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -203,7 +203,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId) } // only warlock armor/skin have this (in additional to family cases) - if( spellInfo->SpellVisual == 130 && spellInfo->SpellIconID == 89) + if( spellInfo->SpellVisual[0] == 130 && spellInfo->SpellIconID == 89) { return SPELL_WARLOCK_ARMOR; } @@ -1062,14 +1062,14 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons // Soulstone Resurrection and Twisting Nether (resurrector) if( spellInfo_1->SpellIconID == 92 && spellInfo_2->SpellIconID == 92 && ( - spellInfo_1->SpellVisual == 99 && spellInfo_2->SpellVisual == 0 || - spellInfo_2->SpellVisual == 99 && spellInfo_1->SpellVisual == 0 ) ) + spellInfo_1->SpellVisual[0] == 99 && spellInfo_2->SpellVisual[0] == 0 || + spellInfo_2->SpellVisual[0] == 99 && spellInfo_1->SpellVisual[0] == 0 ) ) return false; // Heart of the Wild and (Primal Instinct (Idol of Terror) triggering spell or Agility) if( spellInfo_1->SpellIconID == 240 && spellInfo_2->SpellIconID == 240 && ( - spellInfo_1->SpellVisual == 0 && spellInfo_2->SpellVisual == 78 || - spellInfo_2->SpellVisual == 0 && spellInfo_1->SpellVisual == 78 ) ) + spellInfo_1->SpellVisual[0] == 0 && spellInfo_2->SpellVisual[0] == 78 || + spellInfo_2->SpellVisual[0] == 0 && spellInfo_1->SpellVisual[0] == 78 ) ) return false; // Personalized Weather (thunder effect should overwrite rainy aura) @@ -1086,7 +1086,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons case SPELLFAMILY_WARRIOR: { // Scroll of Protection and Defensive Stance (multi-family check) - if( spellInfo_1->SpellIconID == 276 && spellInfo_1->SpellVisual == 196 && spellInfo_2->Id == 71) + if( spellInfo_1->SpellIconID == 276 && spellInfo_1->SpellVisual[0] == 196 && spellInfo_2->Id == 71) return false; // Improved Hamstring -> Hamstring (multi-family check) @@ -1098,7 +1098,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons case SPELLFAMILY_DRUID: { // Scroll of Stamina and Leader of the Pack (multi-family check) - if( spellInfo_1->SpellIconID == 312 && spellInfo_1->SpellVisual == 216 && spellInfo_2->Id == 24932 ) + if( spellInfo_1->SpellIconID == 312 && spellInfo_1->SpellVisual[0] == 216 && spellInfo_2->Id == 24932 ) return false; // Dragonmaw Illusion (multi-family check) @@ -1129,11 +1129,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons case SPELLFAMILY_PALADIN: { // Unstable Currents and other -> *Sanctity Aura (multi-family check) - if( spellInfo_2->SpellIconID==502 && spellInfo_1->SpellIconID==502 && spellInfo_1->SpellVisual==969 ) + if( spellInfo_2->SpellIconID==502 && spellInfo_1->SpellIconID==502 && spellInfo_1->SpellVisual[0]==969 ) return false; // *Band of Eternal Champion and Seal of Command(multi-family check) - if( spellId_1 == 35081 && spellInfo_2->SpellIconID==561 && spellInfo_2->SpellVisual==7992) + if( spellId_1 == 35081 && spellInfo_2->SpellIconID==561 && spellInfo_2->SpellVisual[0]==7992) return false; break; @@ -1149,16 +1149,16 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons return false; // Blink & Improved Blink - if( (spellInfo_1->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_2->SpellVisual == 72 && spellInfo_2->SpellIconID == 1499) || - (spellInfo_2->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_1->SpellVisual == 72 && spellInfo_1->SpellIconID == 1499) ) + if( (spellInfo_1->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_2->SpellVisual[0] == 72 && spellInfo_2->SpellIconID == 1499) || + (spellInfo_2->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_1->SpellVisual[0] == 72 && spellInfo_1->SpellIconID == 1499) ) return false; } // Detect Invisibility and Mana Shield (multi-family check) - if( spellInfo_2->Id == 132 && spellInfo_1->SpellIconID == 209 && spellInfo_1->SpellVisual == 968 ) + if( spellInfo_2->Id == 132 && spellInfo_1->SpellIconID == 209 && spellInfo_1->SpellVisual[0] == 968 ) return false; // Combustion and Fire Protection Aura (multi-family check) - if( spellInfo_1->Id == 11129 && spellInfo_2->SpellIconID == 33 && spellInfo_2->SpellVisual == 321 ) + if( spellInfo_1->Id == 11129 && spellInfo_2->SpellIconID == 33 && spellInfo_2->SpellVisual[0] == 321 ) return false; break; @@ -1187,7 +1187,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons return false; } // Detect Invisibility and Mana Shield (multi-family check) - if( spellInfo_1->Id == 132 && spellInfo_2->SpellIconID == 209 && spellInfo_2->SpellVisual == 968 ) + if( spellInfo_1->Id == 132 && spellInfo_2->SpellIconID == 209 && spellInfo_2->SpellVisual[0] == 968 ) return false; break; case SPELLFAMILY_WARRIOR: @@ -1209,11 +1209,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons return false; // Defensive Stance and Scroll of Protection (multi-family check) - if( spellInfo_1->Id == 71 && spellInfo_2->SpellIconID == 276 && spellInfo_2->SpellVisual == 196 ) + if( spellInfo_1->Id == 71 && spellInfo_2->SpellIconID == 276 && spellInfo_2->SpellVisual[0] == 196 ) return false; // Bloodlust and Bloodthirst (multi-family check) - if( spellInfo_2->Id == 2825 && spellInfo_1->SpellIconID == 38 && spellInfo_1->SpellVisual == 0 ) + if( spellInfo_2->Id == 2825 && spellInfo_1->SpellIconID == 38 && spellInfo_1->SpellVisual[0] == 0 ) return false; break; @@ -1258,7 +1258,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons } // Leader of the Pack and Scroll of Stamina (multi-family check) - if( spellInfo_1->Id == 24932 && spellInfo_2->SpellIconID == 312 && spellInfo_2->SpellVisual == 216 ) + if( spellInfo_1->Id == 24932 && spellInfo_2->SpellIconID == 312 && spellInfo_2->SpellVisual[0] == 216 ) return false; // Dragonmaw Illusion (multi-family check) @@ -1275,7 +1275,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons } // Garrote -> Garrote-Silence (multi-family check) - if( spellInfo_1->SpellIconID == 498 && spellInfo_2->SpellIconID == 498 && spellInfo_2->SpellVisual == 0 ) + if( spellInfo_1->SpellIconID == 498 && spellInfo_2->SpellIconID == 498 && spellInfo_2->SpellVisual[0] == 0 ) return false; break; case SPELLFAMILY_HUNTER: @@ -1312,15 +1312,15 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons return true; } // Combustion and Fire Protection Aura (multi-family check) - if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual == 321 ) + if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual[0] == 321 ) return false; // *Sanctity Aura -> Unstable Currents and other (multi-family check) - if( spellInfo_1->SpellIconID==502 && spellInfo_2->SpellFamilyName == SPELLFAMILY_GENERIC && spellInfo_2->SpellIconID==502 && spellInfo_2->SpellVisual==969 ) + if( spellInfo_1->SpellIconID==502 && spellInfo_2->SpellFamilyName == SPELLFAMILY_GENERIC && spellInfo_2->SpellIconID==502 && spellInfo_2->SpellVisual[0]==969 ) return false; // *Seal of Command and Band of Eternal Champion (multi-family check) - if( spellInfo_1->SpellIconID==561 && spellInfo_1->SpellVisual==7992 && spellId_2 == 35081) + if( spellInfo_1->SpellIconID==561 && spellInfo_1->SpellVisual[0]==7992 && spellId_2 == 35081) return false; break; case SPELLFAMILY_SHAMAN: @@ -1336,7 +1336,7 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons return false; } // Bloodlust and Bloodthirst (multi-family check) - if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual == 0 ) + if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual[0] == 0 ) return false; break; default: diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 222833a63..9c739a589 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -234,12 +234,12 @@ enum SpellFamilyNames SPELLFAMILY_HUNTER = 9, SPELLFAMILY_PALADIN = 10, SPELLFAMILY_SHAMAN = 11, - SPELLFAMILY_UNK2 = 12, + SPELLFAMILY_UNK2 = 12, // 2 spells (silence resistance) SPELLFAMILY_POTION = 13, // 14 - unused SPELLFAMILY_DEATHKNIGHT = 15, // 16 - unused - SPELLFAMILY_UNK3 = 17 + SPELLFAMILY_PET = 17 }; //Some SpellFamilyFlags diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 5860d8261..cfb0702cd 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -6023,7 +6023,7 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB break; } // Shadowguard - if((auraSpellInfo->SpellFamilyFlags & 0x80000000LL) && auraSpellInfo->SpellVisual==7958) + if((auraSpellInfo->SpellFamilyFlags & 0x80000000LL) && auraSpellInfo->SpellVisual[0]==7958) { switch(triggeredByAura->GetSpellProto()->Id) { @@ -6382,14 +6382,14 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB } // Water Shield (we can't set cooldown for main spell - it's player casted spell - if((auraSpellInfo->SpellFamilyFlags & 0x0000002000000000LL) && auraSpellInfo->SpellVisual==7358) + if((auraSpellInfo->SpellFamilyFlags & 0x0000002000000000LL) && auraSpellInfo->SpellVisual[0]==7358) { target = this; break; } // Lightning Shield - if((auraSpellInfo->SpellFamilyFlags & 0x00000400) && auraSpellInfo->SpellVisual==37) + if((auraSpellInfo->SpellFamilyFlags & 0x00000400) && auraSpellInfo->SpellVisual[0]==37) { // overwrite non existing triggered spell call in spell.dbc switch(triggeredByAura->GetSpellProto()->Id) @@ -6475,21 +6475,21 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit *pVictim, int32 scriptId, uint { 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; @@ -7772,7 +7772,7 @@ uint32 Unit::SpellHealingBonus(SpellEntry const *spellProto, uint32 healamount, AuraList const& mDummyAuras = pVictim->GetAurasByType(SPELL_AURA_DUMMY); for(AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i) { - if((*i)->GetSpellProto()->SpellVisual == 9180) + if((*i)->GetSpellProto()->SpellVisual[0] == 9180) { // Flash of Light if ((spellProto->SpellFamilyFlags & 0x0000000040000000LL) && (*i)->GetEffIndex() == 1) diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index c98c87fb1..ab5ef29f3 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -1088,8 +1088,7 @@ struct SpellEntry //uint32 EffectSpellClassMaskA[3]; // 125-127 m_effectSpellClassMaskA not used //uint32 EffectSpellClassMaskB[3]; // 128-130 m_effectSpellClassMaskB not used //uint32 EffectSpellClassMaskC[3]; // 131-133 m_effectSpellClassMaskC not used - uint32 SpellVisual; // 134 m_spellVisualID - // 135 not used - no data and name in client? + uint32 SpellVisual[2]; // 134-135 m_spellVisualID uint32 SpellIconID; // 136 m_spellIconID uint32 activeIconID; // 137 m_activeIconID //uint32 spellPriority; // 138 m_spellPriority not used @@ -1107,19 +1106,20 @@ struct SpellEntry uint32 MaxTargetLevel; // 210 m_maxTargetLevel uint32 SpellFamilyName; // 211 m_spellClassSet uint64 SpellFamilyFlags; // 212-213 m_spellClassMask - uint32 MaxAffectedTargets; // 214 m_maxTargets - uint32 DmgClass; // 215 m_defenseType - uint32 PreventionType; // 216 m_preventionType - //uint32 StanceBarOrder; // 217 m_stanceBarOrder not used - float DmgMultiplier[3]; // 218-220 m_effectChainAmplitude - //uint32 MinFactionId; // 221 m_minFactionID not used - //uint32 MinReputation; // 222 m_minReputation not used - //uint32 RequiredAuraVision; // 223 m_requiredAuraVision not used - uint32 TotemCategory[2]; // 224-225 m_requiredTotemCategoryID - int32 AreaId; // 226 m_requiredAreasID - uint32 SchoolMask; // 227 m_schoolMask - uint32 runeCostID; // 228 m_runeCostID - //uint32 spellMissileID; // 229 m_spellMissileID not used + uint32 SpellFamilyFlags2; // 214 addition to m_spellClassMask + 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 AreaId; // 227 m_requiredAreasID + 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) diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 1fbb324d9..c465cf372 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -68,7 +68,7 @@ const char SkillLineAbilityfmt[]="niiiixxiiiiixx"; const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char SpellCastTimefmt[]="nixx"; const char SpellDurationfmt[]="niii"; -const char SpellEntryfmt[]="niiiiiiiiixiiiiiiiiiixxxxiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffxxxxxxxxxixiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiixiiixfffxxxiiiiix"; +const char SpellEntryfmt[]="niiiiiiiiixiiiiiiiiiixxxxiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffxxxxxxxxxiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiix"; const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx"; const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiixx"; const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; From 81693c4c158b5c7b7b86d62c26ae2f30f9f5cb2e Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 3 Nov 2008 14:03:09 +0300 Subject: [PATCH 064/256] Added new quest template fields, updated some enums and opcodes --- sql/wotlk_updates/7_mangos_quest_template.sql | 3 + src/game/GossipDef.cpp | 12 +-- src/game/ObjectMgr.cpp | 28 +++--- src/game/Opcodes.cpp | 2 +- src/game/Opcodes.h | 2 +- src/game/Player.cpp | 30 ++---- src/game/QuestDef.cpp | 92 ++++++++++--------- src/game/QuestDef.h | 47 ++++++---- 8 files changed, 109 insertions(+), 107 deletions(-) create mode 100644 sql/wotlk_updates/7_mangos_quest_template.sql diff --git a/sql/wotlk_updates/7_mangos_quest_template.sql b/sql/wotlk_updates/7_mangos_quest_template.sql new file mode 100644 index 000000000..8d387ff8b --- /dev/null +++ b/sql/wotlk_updates/7_mangos_quest_template.sql @@ -0,0 +1,3 @@ +alter table `quest_template` + add column `PlayersSlain` tinyint(3) UNSIGNED DEFAULT '0' NOT NULL after `CharTitleId`, + add column `BonusTalents` tinyint(3) UNSIGNED DEFAULT '0' NOT NULL after `PlayersSlain`; diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index 36a83a84e..04d13158d 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -128,7 +128,7 @@ void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ) data << npcGUID; data << uint32(0); // new 2.4.0 data << uint32( TitleTextId ); - data << uint32( mGossipMenu.MenuItemCount() ); // max count 0x0F + data << uint32( mGossipMenu.MenuItemCount() ); // max count 0x0F for ( unsigned int iI = 0; iI < mGossipMenu.MenuItemCount(); iI++ ) { @@ -141,7 +141,7 @@ void PlayerMenu::SendGossipMenu( uint32 TitleTextId, uint64 npcGUID ) data << gItem.m_gBoxMessage; // accept text (related to money) pop up box, 2.0.3 } - data << uint32( mQuestMenu.MenuItemCount() ); // max count 0x20 + data << uint32( mQuestMenu.MenuItemCount() ); // max count 0x20 for ( uint16 iI = 0; iI < mQuestMenu.MenuItemCount(); iI++ ) { @@ -466,7 +466,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(0); // new wotlk + data << uint32(pQuest->GetBonusTalents()); // bonus talents data << uint32(QUEST_EMOTE_COUNT); for (uint32 i=0; i < QUEST_EMOTE_COUNT; i++) @@ -543,8 +543,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(0); // added in WotLK, dunno if it's correct offset (build 8391) - data << uint32(0); // added in WotLK, dunno if it's correct offset (build 8471) + data << uint32(pQuest->GetPlayersSlain()); // players slain + data << uint32(pQuest->GetBonusTalents()); // bonus talents int iI; @@ -683,7 +683,7 @@ void PlayerMenu::SendQuestGiverOfferReward( 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(0); // Honor points reward, not implemented - data << uint32(0); // new wotlk + data << uint32(pQuest->GetBonusTalents()); // new wotlk pSession->SendPacket( &data ); sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_OFFER_REWARD NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() ); } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 03b4e7042..f17a3899a 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -2835,31 +2835,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 + // 71 72 73 74 75 76 "RewChoiceItemId1, RewChoiceItemId2, RewChoiceItemId3, RewChoiceItemId4, RewChoiceItemId5, RewChoiceItemId6," - // 75 76 77 78 79 80 + // 77 78 79 80 81 82 "RewChoiceItemCount1, RewChoiceItemCount2, RewChoiceItemCount3, RewChoiceItemCount4, RewChoiceItemCount5, RewChoiceItemCount6," - // 81 82 83 84 85 86 87 88 + // 83 84 85 86 87 88 89 90 "RewItemId1, RewItemId2, RewItemId3, RewItemId4, RewItemCount1, RewItemCount2, RewItemCount3, RewItemCount4," - // 89 90 91 92 93 94 95 96 97 98 + // 91 92 93 94 95 96 97 98 99 100 "RewRepFaction1, RewRepFaction2, RewRepFaction3, RewRepFaction4, RewRepFaction5, RewRepValue1, RewRepValue2, RewRepValue3, RewRepValue4, RewRepValue5," - // 99 100 101 102 103 104 105 106 107 108 109 + // 101 102 103 104 105 106 107 108 109 110 111 "RewHonorableKills, RewOrReqMoney, RewMoneyMaxLevel, RewSpell, RewSpellCast, RewMailTemplateId, RewMailDelaySecs, PointMapId, PointX, PointY, PointOpt," - // 110 111 112 113 114 115 116 117 118 119 + // 112 113 114 115 116 117 118 119 120 121 "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4,IncompleteEmote, CompleteEmote, OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4," - // 120 121 + // 122 123 "StartScript, CompleteScript" " FROM quest_template"); if(result == NULL) diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index ce4c9d159..7a2f65cff 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -1121,7 +1121,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*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*/ { "SMSG_CALENDAR_EVENT_RESERVED_2", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x447*/ { "CMSG_CALENDAR_GET_CALENDAR_ON_LOGIN",STATUS_LOGGEDIN,&WorldSession::HandleCalendarGetCalendar }, /*0x448*/ { "SMSG_CALENDAR_EVENT_RESERVED_3", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x449*/ { "CMSG_SAVE_DANCE", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x44A*/ { "SMSG_NOTIFY_DANCE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 969ead4ef..8b20c7f74 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1123,7 +1123,7 @@ enum Opcodes SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x444, SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x445, CMSG_CALENDAR_COMPLAIN = 0x446, - SMSG_CALENDAR_EVENT_RESERVED_2 = 0x447, // CMSG_CALENDAR_GET_CALENDAR in 9155 + CMSG_CALENDAR_GET_CALENDAR_ON_LOGIN = 0x447, SMSG_CALENDAR_EVENT_RESERVED_3 = 0x448, CMSG_SAVE_DANCE = 0x449, SMSG_NOTIFY_DANCE = 0x44A, diff --git a/src/game/Player.cpp b/src/game/Player.cpp index bcc975f19..992c73fd8 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -13392,7 +13392,7 @@ void Player::SendQuestComplete( uint32 quest_id ) if( quest_id ) { WorldPacket data( SMSG_QUESTUPDATE_COMPLETE, 4 ); - data << quest_id; + data << uint32(quest_id); GetSession()->SendPacket( &data ); sLog.outDebug( "WORLD: Sent SMSG_QUESTUPDATE_COMPLETE quest = %u", quest_id ); } @@ -13400,16 +13400,14 @@ void Player::SendQuestComplete( uint32 quest_id ) void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGiver ) { - // TODO: something really wrong here (there is only 5 x uint32 in client) uint32 questid = pQuest->GetQuestId(); sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_QUEST_COMPLETE quest = %u", 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 @@ -13417,17 +13415,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, HONORAWARD - data << uint32(0); // added in WotLK, LEVEL_UP_CHAR_POINTS - 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*MaNGOS::Honor::hk_honor_at_level(pSession->GetPlayer()->getLevel(), pQuest->GetRewHonorableKills())); + data << uint32(pQuest->GetBonusTalents()); // bonus talents GetSession()->SendPacket( &data ); if (pQuest->GetQuestCompleteScript() != 0) @@ -13440,7 +13430,7 @@ void Player::SendQuestFailed( uint32 quest_id ) { WorldPacket data( SMSG_QUESTGIVER_QUEST_FAILED, 4+4 ); data << quest_id; - data << uint32(0); // added in WotLK? + data << uint32(0); // failed reason (4 for inventory is full) GetSession()->SendPacket( &data ); sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_FAILED"); } @@ -13479,10 +13469,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 ); } diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp index 06a7ed2b4..a8f903bf7 100644 --- a/src/game/QuestDef.cpp +++ b/src/game/QuestDef.cpp @@ -42,88 +42,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[42+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[77+i].GetUInt32(); for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) - RewItemId[i] = questRecord[81+i].GetUInt32(); + RewItemId[i] = questRecord[83+i].GetUInt32(); for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) - RewItemCount[i] = questRecord[85+i].GetUInt32(); + RewItemCount[i] = questRecord[87+i].GetUInt32(); for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) - RewRepFaction[i] = questRecord[89+i].GetUInt32(); + RewRepFaction[i] = questRecord[91+i].GetUInt32(); for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) - RewRepValue[i] = questRecord[94+i].GetInt32(); + RewRepValue[i] = questRecord[96+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(); + RewHonorableKills = questRecord[101].GetUInt32(); + RewOrReqMoney = questRecord[102].GetInt32(); + RewMoneyMaxLevel = questRecord[103].GetUInt32(); + RewSpell = questRecord[104].GetUInt32(); + RewSpellCast = questRecord[105].GetUInt32(); + RewMailTemplateId = questRecord[106].GetUInt32(); + RewMailDelaySecs = questRecord[107].GetUInt32(); + PointMapId = questRecord[108].GetUInt32(); + PointX = questRecord[109].GetFloat(); + PointY = questRecord[110].GetFloat(); + PointOpt = questRecord[111].GetUInt32(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - DetailsEmote[i] = questRecord[110+i].GetUInt32(); + DetailsEmote[i] = questRecord[112+i].GetUInt32(); - IncompleteEmote = questRecord[114].GetUInt32(); - CompleteEmote = questRecord[115].GetUInt32(); + IncompleteEmote = questRecord[116].GetUInt32(); + CompleteEmote = questRecord[117].GetUInt32(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - OfferRewardEmote[i] = questRecord[116+i].GetInt32(); + OfferRewardEmote[i] = questRecord[118+i].GetInt32(); - QuestStartScript = questRecord[120].GetUInt32(); - QuestCompleteScript = questRecord[121].GetUInt32(); + QuestStartScript = questRecord[122].GetUInt32(); + QuestCompleteScript = questRecord[123].GetUInt32(); QuestFlags |= SpecialFlags << 16; diff --git a/src/game/QuestDef.h b/src/game/QuestDef.h index 316209393..8c173fdb7 100644 --- a/src/game/QuestDef.h +++ b/src/game/QuestDef.h @@ -42,30 +42,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 @@ -188,6 +191,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; } @@ -275,6 +280,8 @@ class Quest uint32 LimitTime; uint32 QuestFlags; uint32 CharTitleId; + uint32 PlayersSlain; + uint32 BonusTalents; int32 PrevQuestId; int32 NextQuestId; int32 ExclusiveGroup; From 1c1bc92d5458056b0995cb2fc122c35348ede5b4 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 3 Nov 2008 15:24:27 +0300 Subject: [PATCH 065/256] Compile fix --- src/game/Player.cpp | 2 +- src/game/QuestHandler.cpp | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 4c6a4af35..082069e0e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -13393,7 +13393,7 @@ void Player::SendQuestReward( Quest const *pQuest, uint32 XP, Object * questGive data << uint32(pQuest->GetRewOrReqMoney() + int32(pQuest->GetRewMoneyMaxLevel() * sWorld.getRate(RATE_DROP_MONEY))); } - data << uint32(10*MaNGOS::Honor::hk_honor_at_level(pSession->GetPlayer()->getLevel(), pQuest->GetRewHonorableKills())); + data << uint32(10*MaNGOS::Honor::hk_honor_at_level(getLevel(), pQuest->GetRewHonorableKills())); data << uint32(pQuest->GetBonusTalents()); // bonus talents GetSession()->SendPacket( &data ); diff --git a/src/game/QuestHandler.cpp b/src/game/QuestHandler.cpp index 5b68829ab..bbb3fa764 100644 --- a/src/game/QuestHandler.cpp +++ b/src/game/QuestHandler.cpp @@ -441,12 +441,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 ); From 5114c17da2bfd6d3b9f73cfd208b420afd90b738 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 3 Nov 2008 18:58:32 +0300 Subject: [PATCH 066/256] Packet fixes --- src/game/GossipDef.cpp | 28 ++++++++++-------- src/game/MovementHandler.cpp | 2 +- src/game/Object.cpp | 6 ++-- src/game/Player.cpp | 3 +- src/game/Spell.cpp | 56 +++++++++++++++++++----------------- src/game/Unit.cpp | 22 +++++++------- src/game/Unit.h | 5 ++-- src/game/UpdateData.h | 2 +- 8 files changed, 65 insertions(+), 59 deletions(-) diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index 04d13158d..06e51aee0 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -375,8 +375,7 @@ void PlayerMenu::SendQuestGiverQuestList( QEmote eEmote, std::string Title, uint data << title; } pSession->SendPacket( &data ); - //uint32 fqid=pQuestMenu->GetItem(0).m_qId; - //sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_QUEST_LIST NPC Guid=%u, questid-0=%u",npcGUID,fqid); + sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_LIST NPC Guid=%u", GUID_LOPART(npcGUID)); } void PlayerMenu::SendQuestGiverStatus( uint8 questStatus, uint64 npcGUID ) @@ -386,7 +385,7 @@ void PlayerMenu::SendQuestGiverStatus( uint8 questStatus, uint64 npcGUID ) data << uint8(questStatus); pSession->SendPacket( &data ); - sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC Guid=%u, status=%u",GUID_LOPART(npcGUID),questStatus); + sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_STATUS NPC Guid=%u, status=%u", GUID_LOPART(npcGUID), questStatus); } void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID, bool ActivateAccept ) @@ -416,9 +415,11 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID } data << uint64(npcGUID); - data << uint64(0); // wotlk + 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 @@ -458,6 +459,7 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID else data << uint32(0); } + data << uint32(pQuest->GetRewOrReqMoney()); } @@ -476,7 +478,7 @@ void PlayerMenu::SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID } pSession->SendPacket( &data ); - sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId()); + sLog.outDebug("WORLD: Sent SMSG_QUESTGIVER_QUEST_DETAILS NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), pQuest->GetQuestId()); } void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest ) @@ -600,7 +602,7 @@ void PlayerMenu::SendQuestQueryResponse( Quest const *pQuest ) 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 ) @@ -682,10 +684,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(0); // Honor points reward, not implemented - data << uint32(pQuest->GetBonusTalents()); // new wotlk + 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 ) @@ -761,8 +763,10 @@ void PlayerMenu::SendQuestGiverRequestItems( Quest const *pQuest, uint64 npcGUID else data << uint32(0x03); - data << uint32(0x04) << uint32(0x08) << uint32(0x10); + data << uint32(0x04); + data << uint32(0x08); + data << uint32(0x10); pSession->SendPacket( &data ); - sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u",GUID_LOPART(npcGUID),pQuest->GetQuestId() ); + sLog.outDebug( "WORLD: Sent SMSG_QUESTGIVER_REQUEST_ITEMS NPCGuid=%u, questid=%u", GUID_LOPART(npcGUID), pQuest->GetQuestId() ); } diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index d1cf3a9ed..d88b35222 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -466,7 +466,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", "Walkback", "Swim", "Swimback", "Turn", "Fly", "Flyback" }; + static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "Walkback", "Swim", "Swimback", "Turn", "Fly", "Flyback", "Pitch" }; uint16 opcode = recv_data.GetOpcode(); switch(opcode) diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 67b5d7782..f2c9e168a 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -386,7 +386,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 *data << ((Unit*)this)->GetSpeed( MOVE_FLY ); *data << ((Unit*)this)->GetSpeed( MOVE_FLYBACK ); *data << ((Unit*)this)->GetSpeed( MOVE_TURN ); - *data << float(7); + *data << ((Unit*)this)->GetSpeed( MOVE_PITCH ); // 0x08000000 if(flags2 & MOVEMENTFLAG_SPLINE2) @@ -539,10 +539,10 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 } // 0x80 - if(flags & UPDATEFLAG_WOTLK) // unused for now + if(flags & UPDATEFLAG_VEHICLE) // unused for now { + *data << uint32(0); // vehicle id *data << float(0); - *data << uint32(0); } } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 082069e0e..4ee84ebc9 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -747,9 +747,8 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da data << (uint32)damage; data << (uint32)0; data << (uint32)0; - //m_session->SendPacket(&data); - //Let other players see that you get damage SendMessageToSet(&data, true); + DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); if(type==DAMAGE_FALL && !isAlive()) // DealDamage not apply item durability loss at self damage diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index e0bdcc001..c41bc519c 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2584,18 +2584,18 @@ 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 + /*else { WorldPacket data(SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE, (8+4)); data.append(m_caster->GetPackGUID()); data << uint32(m_spellInfo->Id); ((Player*)m_caster)->GetSession()->SendPacket(&data); - } + }*/ } void Spell::SendSpellStart() @@ -2603,13 +2603,13 @@ void Spell::SendSpellStart() if(!IsNeedSendToClient()) return; - sLog.outDebug("Sending SMSG_SPELL_START id=%u",m_spellInfo->Id); + sLog.outDebug("Sending SMSG_SPELL_START id=%u", m_spellInfo->Id); uint32 castFlags = CAST_FLAG_UNKNOWN1; if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; - Unit * target; + Unit *target; if(!m_targets.getUnitTarget()) target = m_caster; else @@ -2800,7 +2800,7 @@ void Spell::SendLogExecute() data << uint32(count1); // count1 (effect count?) for(uint32 i = 0; i < count1; ++i) { - data << uint32(m_spellInfo->Effect[0]); // spell effect? + data << uint32(m_spellInfo->Effect[0]); // spell effect uint32 count2 = 1; data << uint32(count2); // count2 (target count?) for(uint32 j = 0; j < count2; ++j) @@ -2846,30 +2846,19 @@ void Spell::SendLogExecute() data << uint8(0); break; case SPELL_EFFECT_CREATE_ITEM: + case SPELL_EFFECT_157: 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()) @@ -2888,6 +2877,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; } @@ -2927,7 +2923,7 @@ void Spell::SendChannelUpdate(uint32 time) WorldPacket data( MSG_CHANNEL_UPDATE, 8+4 ); data.append(m_caster->GetPackGUID()); - data << time; + data << uint32(time); ((Player*)m_caster)->GetSession()->SendPacket( &data ); } @@ -2964,8 +2960,8 @@ void Spell::SendChannelStart(uint32 duration) { WorldPacket data( MSG_CHANNEL_START, (8+4+4) ); data.append(m_caster->GetPackGUID()); - data << m_spellInfo->Id; - data << duration; + data << uint32(m_spellInfo->Id); + data << uint32(duration); ((Player*)m_caster)->GetSession()->SendPacket( &data ); } @@ -2979,9 +2975,15 @@ 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); + data << uint64(m_caster->GetGUID()); + uint32 count = 1; + data << uint32(count); // amount of bytes to read + for(uint32 i = 0; i < count; ++i) + data << uint8(0); + + data << uint8(0); + data << uint8(0); target->GetSession()->SendPacket(&data); } @@ -2991,8 +2993,8 @@ void Spell::SendPlaySpellVisual(uint32 SpellID) return; WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12); - data << m_caster->GetGUID(); - data << SpellID; + data << uint64(m_caster->GetGUID()); + data << uint32(SpellID); // spell visual id? ((Player*)m_caster)->GetSession()->SendPacket(&data); } @@ -4163,7 +4165,7 @@ uint8 Spell::CheckCasterAuras() const else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY) prevented_reason = SPELL_FAILED_PACIFIED; - // Attr must make flag drop spell totally immuned from all effects + // Attr must make flag drop spell totally immune from all effects if(prevented_reason) { if(school_immune || mechanic_immune || dispel_immune) @@ -4630,7 +4632,7 @@ uint8 Spell::CheckItems() return SPELL_FAILED_CANT_BE_DISENCHANTED; uint32 item_quality = itemProto->Quality; - // 2.0.x addon: Check player enchanting level agains the item desenchanting requirements + // 2.0.x addon: Check player enchanting level against the item desenchanting requirements uint32 item_disenchantskilllevel = itemProto->RequiredDisenchantSkill; if (item_disenchantskilllevel == uint32(-1)) return SPELL_FAILED_CANT_BE_DISENCHANTED; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index d4590628d..95ac8ffc1 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -56,6 +56,7 @@ float baseMoveSpeed[MAX_MOVE_TYPE] = 3.141594f, // MOVE_TURN 7.0f, // MOVE_FLY 4.5f, // MOVE_FLYBACK + 3.14f // MOVE_PITCH }; // auraTypes contains attacker auras capable of proc'ing cast auras @@ -1470,9 +1471,8 @@ uint32 Unit::SpellNonMeleeDamageLog(Unit *pVictim, uint32 spellID, uint32 damage 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); } @@ -1665,7 +1665,7 @@ void Unit::CalcAbsorbResist(Unit *pVictim,SpellSchoolMask schoolMask, DamageEffe RemainingDamage -= currentAbsorb; } - // only split damage if not damaing yourself + // only split damage if not damaging yourself if(pVictim != this) { AuraList const& vSplitDamageFlat = pVictim->GetAurasByType(SPELL_AURA_SPLIT_DAMAGE_FLAT); @@ -2585,8 +2585,8 @@ float Unit::CalculateLevelPenalty(SpellEntry const* spellProto) const void Unit::SendAttackStart(Unit* pVictim) { WorldPacket data( SMSG_ATTACKSTART, 16 ); - data << GetGUID(); - data << pVictim->GetGUID(); + data << uint64(GetGUID()); + data << uint64(pVictim->GetGUID()); SendMessageToSet(&data, true); DEBUG_LOG( "WORLD: Sent SMSG_ATTACKSTART" ); @@ -3847,7 +3847,7 @@ bool Unit::RemoveNoStackAurasDueToAura(Aura *Aur) if(is_triggered_by_spell) break; - // prevent remove form main spell by triggred passive spells + // 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: @@ -6924,7 +6924,7 @@ bool Unit::Attack(Unit *victim, bool meleeAttack) if(GetTypeId()==TYPEID_UNIT) { WorldPacket data(SMSG_AI_REACTION, 12); - data << GetGUID(); + data << uint64(GetGUID()); data << uint32(AI_REACTION_AGGRO); // Aggro sound ((WorldObject*)this)->SendMessageToSet(&data, true); @@ -7174,6 +7174,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); @@ -7187,7 +7188,6 @@ void Unit::SendEnergizeSpellLog(Unit *pVictim, uint32 SpellID, uint32 Damage, Po data << uint32(SpellID); data << uint32(powertype); data << uint32(Damage); - //data << uint8(critical ? 1 : 0); // removed in 2.4.0 SendMessageToSet(&data, true); } @@ -7644,7 +7644,7 @@ int32 Unit::SpellBaseDamageBonusForVictim(SpellSchoolMask schoolMask, Unit *pVic bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType) { - // not criting spell + // not critting spell if((spellProto->AttributesEx2 & SPELL_ATTR_EX2_CANT_CRIT)) return false; @@ -8327,7 +8327,7 @@ void Unit::ApplySpellDispelImmunity(const SpellEntry * spellProto, DispelType ty float Unit::GetWeaponProcChance() const { // normalized proc chance for weapon attack speed - // (odd formulae...) + // (odd formula...) if(isAttackReady(BASE_ATTACK)) return (GetAttackTime(BASE_ATTACK) * 1.8f / 1000.0f); else if (haveOffhandWeapon() && isAttackReady(OFF_ATTACK)) diff --git a/src/game/Unit.h b/src/game/Unit.h index 5e4306656..e3ef72b73 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -383,10 +383,11 @@ enum UnitMoveType MOVE_SWIMBACK = 4, MOVE_TURN = 5, MOVE_FLY = 6, - MOVE_FLYBACK = 7 + MOVE_FLYBACK = 7, + MOVE_PITCH = 8 }; -#define MAX_MOVE_TYPE 8 +#define MAX_MOVE_TYPE 9 extern float baseMoveSpeed[MAX_MOVE_TYPE]; diff --git a/src/game/UpdateData.h b/src/game/UpdateData.h index 0f55971b6..b4ddc1c9b 100644 --- a/src/game/UpdateData.h +++ b/src/game/UpdateData.h @@ -41,7 +41,7 @@ enum OBJECT_UPDATE_FLAGS UPDATEFLAG_HIGHGUID = 0x10, UPDATEFLAG_LIVING = 0x20, UPDATEFLAG_HASPOSITION = 0x40, - UPDATEFLAG_WOTLK = 0x80 + UPDATEFLAG_VEHICLE = 0x80 }; class UpdateData From 3d86187c4a767dc8ab77e7c7f0003636fad3d4fc Mon Sep 17 00:00:00 2001 From: arrai Date: Tue, 4 Nov 2008 00:52:42 +0100 Subject: [PATCH 067/256] Implemented ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM Added basic support for timed achievements --- src/game/AchievementMgr.cpp | 28 ++++++++++++++++++++++++++++ src/game/Spell.cpp | 3 +++ src/shared/Database/DBCEnums.h | 1 + src/shared/Database/DBCStructure.h | 2 +- src/shared/Database/DBCfmt.cpp | 2 +- 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 3cb56dc7e..690ea9dc3 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -90,6 +90,14 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri { Field *fields = criteriaResult->Fetch(); CriteriaProgress *progress = new CriteriaProgress(fields[0].GetUInt32(), fields[1].GetUInt32(), fields[2].GetUInt64()); + + AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(progress->id); + if(!criteria || + criteria->timeLimit && progress->date + criteria->timeLimit < time(NULL)) + { + delete progress; + continue; + } m_criteriaProgress[progress->id] = progress; } while(criteriaResult->NextRow()); delete criteriaResult; @@ -305,6 +313,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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; } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); @@ -377,6 +393,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: @@ -448,6 +466,16 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, return; progress->counter = newValue; } + 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(progress); } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index c41bc519c..888bf8757 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2081,6 +2081,9 @@ void Spell::cast(bool skipCheck) // set to real guid to be sent later to the client m_targets.updateTradeSlotItem(); + if(m_CastItem && m_caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry()); + // CAST SPELL SendSpellCooldown(); diff --git a/src/shared/Database/DBCEnums.h b/src/shared/Database/DBCEnums.h index 83cd83d40..ebe0e6ae1 100644 --- a/src/shared/Database/DBCEnums.h +++ b/src/shared/Database/DBCEnums.h @@ -36,6 +36,7 @@ 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, diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index ab5ef29f3..4aa97397c 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -52,7 +52,7 @@ struct AchievementEntry //char *unk1[16]; // 43-58 //uint32 unk_flags; // 59 //uint32 count; // 60 - //uint32 refAchievement; // 61 + uint32 refAchievement; // 61 }; struct AchievementCategoryEntry diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index c465cf372..a80a94ace 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -16,7 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -const char Achievementfmt[]="niixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxxx"; +const char Achievementfmt[]="niixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxxxxxxxxxi"; const char AchievementCriteriafmt[]="niiiiiiiixxxxxxxxxxxxxxxxxiixix"; const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxixxxxxxx"; const char AreaTriggerEntryfmt[]="niffffffff"; From e5a597ea9fa5438140665bf26163a0193c82e63d Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 3 Nov 2008 15:53:49 +0300 Subject: [PATCH 068/256] Small fixes in genrevision --- src/tools/genrevision/genrevision.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/genrevision/genrevision.cpp b/src/tools/genrevision/genrevision.cpp index c66fd6d7b..9367addc1 100644 --- a/src/tools/genrevision/genrevision.cpp +++ b/src/tools/genrevision/genrevision.cpp @@ -98,7 +98,7 @@ void extractDataFromGit(FILE* EntriesFile, std::string path, bool url, RawData& } else { - int res = sscanf(url_str,"git://%s",url_buf); + res = sscanf(url_str,"git://%s",url_buf); if(res) { host_str = strtok(url_buf,"/"); @@ -127,7 +127,7 @@ void extractDataFromGit(FILE* EntriesFile, std::string path, bool url, RawData& char buf2[200]; char new_hash[200]; int unix_time = 0; - int res2 = sscanf(buf,"%s %s %s %s %i",buf2,new_hash,buf2,buf2,&unix_time,buf2); + int res2 = sscanf(buf,"%s %s %s %s %i",buf2,new_hash,buf2,buf2,&unix_time); if(res2!=5) continue; From b2d24ba0f7fe4d21b03fb2d02f5467c5c0eeb0af Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Tue, 4 Nov 2008 04:35:28 +0300 Subject: [PATCH 069/256] Packet fixes, pet spells --- src/game/Corpse.cpp | 2 +- src/game/DynamicObject.cpp | 2 +- src/game/GameObject.cpp | 2 +- src/game/MiscHandler.cpp | 4 +- src/game/Object.cpp | 33 ++--- src/game/Object.h | 2 +- src/game/Pet.cpp | 17 ++- src/game/Pet.h | 1 + src/game/PetHandler.cpp | 3 + src/game/Player.h | 2 +- src/game/SharedDefines.h | 2 +- src/game/SpellMgr.cpp | 189 ++++++++++++++++++++++++++++- src/game/SpellMgr.h | 20 +++ src/game/Transports.cpp | 2 +- src/game/Unit.cpp | 2 +- src/game/UpdateData.h | 4 +- src/game/World.cpp | 3 + src/shared/Database/DBCStructure.h | 2 +- 18 files changed, 262 insertions(+), 30 deletions(-) diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp index c2a873a1b..1523fe673 100644 --- a/src/game/Corpse.cpp +++ b/src/game/Corpse.cpp @@ -34,7 +34,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; diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp index 86d621905..970209d7a 100644 --- a/src/game/DynamicObject.cpp +++ b/src/game/DynamicObject.cpp @@ -36,7 +36,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; } diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 2544640c5..e9841e4fc 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -42,7 +42,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; diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 29bb37bc1..10c6f1f8a 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -547,12 +547,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, !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); + GetPlayer()->ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_PVP_TIMER); } if(GetPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_IN_PVP)) diff --git a/src/game/Object.cpp b/src/game/Object.cpp index f2c9e168a..444930632 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -146,15 +146,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 +174,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); @@ -255,7 +255,7 @@ void Object::DestroyForPlayer(Player *target) const 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); @@ -298,7 +298,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 } // 0x40 - if (flags & UPDATEFLAG_HASPOSITION) + if (flags & UPDATEFLAG_HAS_POSITION) { // 0x02 if(flags & UPDATEFLAG_TRANSPORT && ((GameObject*)this)->GetGoType() == GAMEOBJECT_TYPE_MO_TRANSPORT) @@ -512,13 +512,13 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 *data << uint32(GetGUIDHigh()); // GetGUIDHigh() break; case TYPEID_UNIT: - *data << uint32(-1); + *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(-1); // unk, can be 0x7 or 0x8 + *data << uint32(0x00000008); // unk, can be 0x7 or 0x8 break; default: *data << uint32(0x00000000); // unk @@ -527,9 +527,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 @@ -542,7 +545,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2 if(flags & UPDATEFLAG_VEHICLE) // unused for now { *data << uint32(0); // vehicle id - *data << float(0); + *data << float(0); // facing adjustment } } @@ -646,7 +649,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *data << uint32(1); break; default: - *data << uint32(0); //unknown. not happen. + *data << uint32(0); // unknown. not happen. break; } } diff --git a/src/game/Object.h b/src/game/Object.h index d71da5622..45d86efaa 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -317,7 +317,7 @@ class MANGOS_DLL_SPEC Object { int32 *m_int32Values; uint32 *m_uint32Values; - float *m_floatValues; + float *m_floatValues; }; uint32 *m_uint32Values_mirror; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 9c16b2fca..d18cccda7 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -904,7 +904,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel) case HUNTER_PET: { SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, uint32((MaNGOS::XP::xp_to_level(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)) ); @@ -1331,6 +1331,21 @@ bool Pet::learnSpell(uint16 spell_id) return true; } +void Pet::learnLevelupSpells() +{ + PetLevelupSpellList const *levelupSpells = spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family); + if(!levelupSpells) + return; + + for(PetLevelupSpellList::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr) + { + if(itr->ReqLevel <= getLevel()) + learnSpell(itr->SpellId); + else + removeSpell(itr->SpellId); + } +} + void Pet::removeSpell(uint16 spell_id) { PetSpellMap::iterator itr = m_spells.find(spell_id); diff --git a/src/game/Pet.h b/src/game/Pet.h index ab349fc72..cbabb3985 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -190,6 +190,7 @@ class Pet : public Creature 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 learnLevelupSpells(); void removeSpell(uint16 spell_id); bool _removeSpell(uint16 spell_id); diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index e0acefd16..511544afe 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -731,6 +731,9 @@ void WorldSession::HandlePetLearnTalent( WorldPacket & recv_data ) 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; diff --git a/src/game/Player.h b/src/game/Player.h index 50b464293..3473f58c8 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -390,7 +390,7 @@ enum PlayerFlags 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_FLAGS_PVP = 0x00040000, // 3.0.2... + PLAYER_FLAGS_PVP_TIMER = 0x00040000, // 3.0.2, pvp timer active (after you disable pvp manually) }; // used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<> Loaded %u spell pet auras", count ); } -/// Some checks for spells, to prevent adding depricated/broken spells for trainers, spell book, etc +void SpellMgr::LoadPetLevelupSpellMap() +{ + PetLevelupSpell petSpell; + CreatureFamilyEntry const *creatureFamily; + SpellEntry const *spell; + uint32 count = 0; + uint32 startTime = getMSTime(); + + 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 & 0x1000000000000000LL)) + continue; + + // not Growl or Cower (generics) + if(spell->SpellIconID != 201 && spell->SpellIconID != 958) + { + switch(creatureFamily->ID) + { + case CREATURE_FAMILY_BAT: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1577) // Bite and Sonic Blast + continue; + break; + case CREATURE_FAMILY_BEAR: + if(spell->SpellIconID != 262 && spell->SpellIconID != 1562) // Claw and Swipe + continue; + break; + case CREATURE_FAMILY_BIRD_OF_PREY: + if(spell->SpellIconID != 262 && spell->SpellIconID != 168) // Claw and Snatch + continue; + case CREATURE_FAMILY_BOAR: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1578) // Bite and Gore + continue; + break; + case CREATURE_FAMILY_CARRION_BIRD: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1579) // Bite and Demoralizing Screech + continue; + break; + case CREATURE_FAMILY_CAT: + if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 494) // Claw and Prowl and Rake + continue; + break; + case CREATURE_FAMILY_CHIMAERA: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) // Bite and Froststorm Breath + continue; + break; + case CREATURE_FAMILY_CORE_HOUND: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1197) // Bite and Lava Breath + continue; + break; + case CREATURE_FAMILY_CRAB: + if(spell->SpellIconID != 262 && spell->SpellIconID != 2679) // Claw and Pin + continue; + break; + case CREATURE_FAMILY_CROCOLISK: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1581) // Bite and Bad Attitude + continue; + break; + case CREATURE_FAMILY_DEVILSAUR: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 599) // Bite and Monstrous Bite + continue; + break; + case CREATURE_FAMILY_DRAGONHAWK: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2128) // Bite and Fire Breath + continue; + break; + case CREATURE_FAMILY_GORILLA: + if(spell->SpellIconID != 473 && spell->SpellIconID != 148) // Smack and Thunderstomp + continue; + break; + case CREATURE_FAMILY_HYENA: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 138) // Bite and Tendon Rip + continue; + break; + case CREATURE_FAMILY_MOTH: + if(spell->SpellIconID != 1714 && spell->SpellIconID != 473) // Serenity Dust and Smack + continue; + break; + case CREATURE_FAMILY_NETHER_RAY: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2027) // Bite and Nether Shock + continue; + break; + case CREATURE_FAMILY_RAPTOR: + if(spell->SpellIconID != 262 && spell->SpellIconID != 245) // Claw and Savage Rend + continue; + break; + case CREATURE_FAMILY_RAVAGER: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2253) // Bite and Ravage + continue; + break; + case CREATURE_FAMILY_RHINO: + if(spell->SpellIconID != 473 && spell->SpellIconID != 3066) // Smack and Stampede + continue; + break; + case CREATURE_FAMILY_SCORPID: + if(spell->SpellIconID != 262 && spell->SpellIconID != 163) // Claw and Scorpid Poison + continue; + break; + case CREATURE_FAMILY_SERPENT: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 68) // Bite and Poison Spit + continue; + break; + case CREATURE_FAMILY_SILITHID: + if(spell->SpellIconID != 262 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 12013)) // Claw and Venom Web Spray + continue; + break; + case CREATURE_FAMILY_SPIDER: + if(spell->SpellIconID != 1680 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 684)) // Bite and Web + continue; + break; + case CREATURE_FAMILY_SPIRIT_BEAST: + if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 255) // Claw and Prowl and Spirit Strike + continue; + break; + case CREATURE_FAMILY_SPOREBAT: + if(spell->SpellIconID != 473 && spell->SpellIconID != 2681) // Smack and Spore Cloud + continue; + break; + case CREATURE_FAMILY_TALLSTRIDER: + if(spell->SpellIconID != 262 (spell->SpellIconID != 157 && (spell->Attributes & 0x4000000))) // Claw and Dust Cloud + continue; + break; + case CREATURE_FAMILY_TURTLE: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1588) // Bite and Shell Shield + continue; + break; + case CREATURE_FAMILY_WARP_STALKER: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1952) // Bite and Warp + continue; + break; + case CREATURE_FAMILY_WASP: + if(spell->SpellIconID != 473 && spell->SpellIconID != 110) // Smack and Sting + continue; + break; + case CREATURE_FAMILY_WIND_SERPENT: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) // Bite and Lightning Breath + continue; + break; + case CREATURE_FAMILY_WOLF: + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1573) // Bite and Furious Howl + continue; + break; + case CREATURE_FAMILY_WORM: + if(spell->SpellIconID != 636 && spell->SpellIconID != 1680) // Acid Spit and Bite + continue; + break; + default: + sLog.outError("LoadPetLevelupSpellMap: Unhandled creature family %u", creatureFamily->ID); + continue; + } + } + + petSpell.SpellId = spell->Id; + petSpell.ReqLevel = spell->spellLevel; + + mPetLevelupSpellMap[creatureFamily->ID].push_back(petSpell); + count++; + } + } + + uint32 diffTime = getMSTimeDiff(startTime, getMSTime()); + sLog.outDebug("took %u ms", diffTime); + + 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 diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 9c739a589..6ae7aac1e 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -626,6 +626,15 @@ typedef std::multimap SpellLearnSpellMap; typedef std::multimap SkillLineAbilityMap; +struct PetLevelupSpell +{ + uint32 SpellId; + uint32 ReqLevel; +}; + +typedef std::list PetLevelupSpellList; +typedef std::map PetLevelupSpellMap; + inline bool IsPrimaryProfessionSkill(uint32 skill) { SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(skill); @@ -841,6 +850,15 @@ class SpellMgr return NULL; } + PetLevelupSpellList 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(); @@ -857,6 +875,7 @@ class SpellMgr void LoadSpellThreats(); void LoadSkillLineAbilityMap(); void LoadSpellPetAuras(); + void LoadPetLevelupSpellMap(); private: SpellScriptTarget mSpellScriptTarget; @@ -870,6 +889,7 @@ class SpellMgr SpellProcEventMap mSpellProcEventMap; SkillLineAbilityMap mSkillLineAbilityMap; SpellPetAuraMap mSpellPetAuraMap; + PetLevelupSpellMap mPetLevelupSpellMap; }; #define spellmgr SpellMgr::Instance() diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index 375bcc1ad..26faa9350 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -135,7 +135,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) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 95ac8ffc1..8b894bb87 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -146,7 +146,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_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION); m_attackTimer[BASE_ATTACK] = 0; m_attackTimer[OFF_ATTACK] = 0; diff --git a/src/game/UpdateData.h b/src/game/UpdateData.h index b4ddc1c9b..aff6d47e5 100644 --- a/src/game/UpdateData.h +++ b/src/game/UpdateData.h @@ -36,11 +36,11 @@ 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 }; diff --git a/src/game/World.cpp b/src/game/World.cpp index 1e29ffc55..f177b86f0 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1060,6 +1060,9 @@ void World::SetInitialWorldSettings() sLog.outString( "Loading spell pet auras..." ); spellmgr.LoadSpellPetAuras(); + sLog.outString( "Loading pet levelup spells..." ); + spellmgr.LoadPetLevelupSpellMap(); + sLog.outString( "Loading player Create Info & Level Stats..." ); objmgr.LoadPlayerInfo(); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 4aa97397c..be9214209 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -613,7 +613,7 @@ struct CreatureFamilyEntry uint32 maxScaleLevel; // 4 m_maxScaleLevel uint32 skillLine[2]; // 5-6 m_skillLine uint32 petFoodMask; // 7 m_petFoodMask - uint32 petTalentType; // 8 m_petTalentType + int32 petTalentType; // 8 m_petTalentType // 9 m_categoryEnumID char* Name[16]; // 10-25 m_name_lang // 26 string flags, unused From 11d52698536a7d3e90acce28076d695b5ce8fef8 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Tue, 4 Nov 2008 04:37:51 +0300 Subject: [PATCH 070/256] Compile fix --- src/game/SpellMgr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 54861fec7..934f734e5 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2107,7 +2107,7 @@ void SpellMgr::LoadPetLevelupSpellMap() continue; break; case CREATURE_FAMILY_TALLSTRIDER: - if(spell->SpellIconID != 262 (spell->SpellIconID != 157 && (spell->Attributes & 0x4000000))) // Claw and Dust Cloud + if(spell->SpellIconID != 262 && (spell->SpellIconID != 157 && (spell->Attributes & 0x4000000))) // Claw and Dust Cloud continue; break; case CREATURE_FAMILY_TURTLE: From 3e8ebb024f5b85ff39b294b6d7691aad92e6cd5e Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Tue, 4 Nov 2008 18:23:52 +0300 Subject: [PATCH 071/256] Fixed: pet spells, possible sql injection, increased sql query size once again --- src/game/Pet.cpp | 27 +++---- src/game/SpellMgr.cpp | 135 ++++++++++++++++----------------- src/game/SpellMgr.h | 2 +- src/game/WorldSession.cpp | 1 + src/shared/Database/Database.h | 2 +- 5 files changed, 83 insertions(+), 84 deletions(-) diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index d18cccda7..56ab76c30 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -1264,7 +1264,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s uint32 chainstart = spellmgr.GetFirstSpellInChain(spell_id); - for (PetSpellMap::iterator 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; @@ -1278,6 +1278,7 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s oldspell_id = itr->first; removeSpell(itr->first); + break; } } @@ -1482,23 +1483,23 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) if(apply) { for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++); - if (i == m_autospells.size()) - { - m_autospells.push_back(spellid); - itr->second->active = ACT_ENABLED; - itr->second->state = PETSPELL_CHANGED; - } + if (i == m_autospells.size()) + { + m_autospells.push_back(spellid); + itr->second->active = ACT_ENABLED; + itr->second->state = PETSPELL_CHANGED; + } } else { AutoSpellList::iterator itr2 = m_autospells.begin(); for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++); - if (i < m_autospells.size()) - { - m_autospells.erase(itr2); - itr->second->active = ACT_DISABLED; - itr->second->state = PETSPELL_CHANGED; - } + if (i < m_autospells.size()) + { + m_autospells.erase(itr2); + itr->second->active = ACT_DISABLED; + itr->second->state = PETSPELL_CHANGED; + } } } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 934f734e5..afb98e34b 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1974,7 +1974,6 @@ void SpellMgr::LoadPetLevelupSpellMap() CreatureFamilyEntry const *creatureFamily; SpellEntry const *spell; uint32 count = 0; - uint32 startTime = getMSTime(); for (uint32 i = 0; i < sCreatureFamilyStore.GetNumRows(); ++i) { @@ -2007,131 +2006,132 @@ void SpellMgr::LoadPetLevelupSpellMap() { switch(creatureFamily->ID) { - case CREATURE_FAMILY_BAT: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1577) // Bite and Sonic Blast + case CREATURE_FAMILY_BAT: // Bite and Sonic Blast + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1577) continue; break; - case CREATURE_FAMILY_BEAR: - if(spell->SpellIconID != 262 && spell->SpellIconID != 1562) // Claw and Swipe + case CREATURE_FAMILY_BEAR: // Claw and Swipe + if(spell->SpellIconID != 262 && spell->SpellIconID != 1562) continue; break; - case CREATURE_FAMILY_BIRD_OF_PREY: - if(spell->SpellIconID != 262 && spell->SpellIconID != 168) // Claw and Snatch - continue; - case CREATURE_FAMILY_BOAR: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1578) // Bite and Gore + case CREATURE_FAMILY_BIRD_OF_PREY: // Claw and Snatch + if(spell->SpellIconID != 262 && spell->SpellIconID != 168) continue; break; - case CREATURE_FAMILY_CARRION_BIRD: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1579) // Bite and Demoralizing Screech + case CREATURE_FAMILY_BOAR: // Bite and Gore + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1578) continue; break; - case CREATURE_FAMILY_CAT: - if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 494) // Claw and Prowl and Rake + case CREATURE_FAMILY_CARRION_BIRD: // Bite and Demoralizing Screech + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1579) continue; break; - case CREATURE_FAMILY_CHIMAERA: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) // Bite and Froststorm Breath + case CREATURE_FAMILY_CAT: // Claw and Prowl and Rake + if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 494) continue; break; - case CREATURE_FAMILY_CORE_HOUND: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1197) // Bite and Lava Breath + case CREATURE_FAMILY_CHIMAERA: // Bite and Froststorm Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) continue; break; - case CREATURE_FAMILY_CRAB: - if(spell->SpellIconID != 262 && spell->SpellIconID != 2679) // Claw and Pin + case CREATURE_FAMILY_CORE_HOUND: // Bite and Lava Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1197) continue; break; - case CREATURE_FAMILY_CROCOLISK: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1581) // Bite and Bad Attitude + case CREATURE_FAMILY_CRAB: // Claw and Pin + if(spell->SpellIconID != 262 && spell->SpellIconID != 2679) continue; break; - case CREATURE_FAMILY_DEVILSAUR: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 599) // Bite and Monstrous Bite + case CREATURE_FAMILY_CROCOLISK: // Bite and Bad Attitude + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1581) continue; break; - case CREATURE_FAMILY_DRAGONHAWK: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 2128) // Bite and Fire Breath + case CREATURE_FAMILY_DEVILSAUR: // Bite and Monstrous Bite + if(spell->SpellIconID != 1680 && spell->SpellIconID != 599) continue; break; - case CREATURE_FAMILY_GORILLA: - if(spell->SpellIconID != 473 && spell->SpellIconID != 148) // Smack and Thunderstomp + case CREATURE_FAMILY_DRAGONHAWK: // Bite and Fire Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2128) continue; break; - case CREATURE_FAMILY_HYENA: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 138) // Bite and Tendon Rip + case CREATURE_FAMILY_GORILLA: // Smack and Thunderstomp + if(spell->SpellIconID != 473 && spell->SpellIconID != 148) continue; break; - case CREATURE_FAMILY_MOTH: - if(spell->SpellIconID != 1714 && spell->SpellIconID != 473) // Serenity Dust and Smack + case CREATURE_FAMILY_HYENA: // Bite and Tendon Rip + if(spell->SpellIconID != 1680 && spell->SpellIconID != 138) continue; break; - case CREATURE_FAMILY_NETHER_RAY: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 2027) // Bite and Nether Shock + case CREATURE_FAMILY_MOTH: // Serenity Dust and Smack + if(spell->SpellIconID != 1714 && spell->SpellIconID != 473) continue; break; - case CREATURE_FAMILY_RAPTOR: - if(spell->SpellIconID != 262 && spell->SpellIconID != 245) // Claw and Savage Rend + case CREATURE_FAMILY_NETHER_RAY: // Bite and Nether Shock + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2027) continue; break; - case CREATURE_FAMILY_RAVAGER: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 2253) // Bite and Ravage + case CREATURE_FAMILY_RAPTOR: // Claw and Savage Rend + if(spell->SpellIconID != 262 && spell->SpellIconID != 245) continue; break; - case CREATURE_FAMILY_RHINO: - if(spell->SpellIconID != 473 && spell->SpellIconID != 3066) // Smack and Stampede + case CREATURE_FAMILY_RAVAGER: // Bite and Ravage + if(spell->SpellIconID != 1680 && spell->SpellIconID != 2253) continue; break; - case CREATURE_FAMILY_SCORPID: - if(spell->SpellIconID != 262 && spell->SpellIconID != 163) // Claw and Scorpid Poison + case CREATURE_FAMILY_RHINO: // Smack and Stampede + if(spell->SpellIconID != 473 && spell->SpellIconID != 3066) continue; break; - case CREATURE_FAMILY_SERPENT: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 68) // Bite and Poison Spit + case CREATURE_FAMILY_SCORPID: // Claw and Scorpid Poison + if(spell->SpellIconID != 262 && spell->SpellIconID != 163) continue; break; - case CREATURE_FAMILY_SILITHID: - if(spell->SpellIconID != 262 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 12013)) // Claw and Venom Web Spray + case CREATURE_FAMILY_SERPENT: // Bite and Poison Spit + if(spell->SpellIconID != 1680 && spell->SpellIconID != 68) continue; break; - case CREATURE_FAMILY_SPIDER: - if(spell->SpellIconID != 1680 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 684)) // Bite and Web + 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_SPIRIT_BEAST: - if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 255) // Claw and Prowl and Spirit Strike + case CREATURE_FAMILY_SPIDER: // Bite and Web + if(spell->SpellIconID != 1680 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 684)) continue; break; - case CREATURE_FAMILY_SPOREBAT: - if(spell->SpellIconID != 473 && spell->SpellIconID != 2681) // Smack and Spore Cloud + 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_TALLSTRIDER: - if(spell->SpellIconID != 262 && (spell->SpellIconID != 157 && (spell->Attributes & 0x4000000))) // Claw and Dust Cloud + case CREATURE_FAMILY_SPOREBAT: // Smack and Spore Cloud + if(spell->SpellIconID != 473 && spell->SpellIconID != 2681) continue; break; - case CREATURE_FAMILY_TURTLE: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1588) // Bite and Shell Shield + case CREATURE_FAMILY_TALLSTRIDER: // Claw and Dust Cloud + if(spell->SpellIconID != 262 && (spell->SpellIconID != 157 && !(spell->Attributes & 0x4000000))) continue; break; - case CREATURE_FAMILY_WARP_STALKER: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1952) // Bite and Warp + 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: - if(spell->SpellIconID != 473 && spell->SpellIconID != 110) // Smack and Sting + case CREATURE_FAMILY_WASP: // Smack and Sting + if(spell->SpellIconID != 473 && spell->SpellIconID != 110) continue; break; - case CREATURE_FAMILY_WIND_SERPENT: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) // Bite and Lightning Breath + case CREATURE_FAMILY_WIND_SERPENT: // Bite and Lightning Breath + if(spell->SpellIconID != 1680 && spell->SpellIconID != 62) continue; break; - case CREATURE_FAMILY_WOLF: - if(spell->SpellIconID != 1680 && spell->SpellIconID != 1573) // Bite and Furious Howl + case CREATURE_FAMILY_WOLF: // Bite and Furious Howl + if(spell->SpellIconID != 1680 && spell->SpellIconID != 1573) continue; break; - case CREATURE_FAMILY_WORM: - if(spell->SpellIconID != 636 && spell->SpellIconID != 1680) // Acid Spit and Bite + case CREATURE_FAMILY_WORM: // Acid Spit and Bite + if(spell->SpellIconID != 636 && spell->SpellIconID != 1680) continue; break; default: @@ -2148,9 +2148,6 @@ void SpellMgr::LoadPetLevelupSpellMap() } } - uint32 diffTime = getMSTimeDiff(startTime, getMSTime()); - sLog.outDebug("took %u ms", diffTime); - sLog.outString(); sLog.outString( ">> Loaded %u pet levelup spells", count ); } diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 6ae7aac1e..87bcdb339 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -632,7 +632,7 @@ struct PetLevelupSpell uint32 ReqLevel; }; -typedef std::list PetLevelupSpellList; +typedef std::vector PetLevelupSpellList; typedef std::map PetLevelupSpellMap; inline bool IsPrimaryProfessionSkill(uint32 skill) diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index b79b13dd3..dc5226488 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -544,5 +544,6 @@ void WorldSession::SetAccountData(uint32 type, time_t time_, std::string data) uint32 acc = GetAccountId(); 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()); } diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index 7751c7a9e..7410b07d3 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -31,7 +31,7 @@ class SqlQueryHolder; typedef HM_NAMESPACE::hash_map TransactionQueues; typedef HM_NAMESPACE::hash_map QueryQueues; -#define MAX_QUERY_LEN 5*1024 +#define MAX_QUERY_LEN 32*1024 class MANGOS_DLL_SPEC Database { From 7adf2001f388227bf071bea9c9be5a2b56fc400c Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Tue, 4 Nov 2008 19:37:22 +0300 Subject: [PATCH 072/256] New client build, level cap is 80 --- src/mangosd/mangosd.conf.dist.in | 2 +- src/realmd/AuthCodes.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index ed2000fb6..b80cf17a6 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -527,7 +527,7 @@ CharactersCreatingDisabled = 0 CharactersPerAccount = 50 CharactersPerRealm = 10 SkipCinematics = 0 -MaxPlayerLevel = 70 +MaxPlayerLevel = 80 MaxHonorPoints = 75000 MaxArenaPoints = 5000 StartPlayerLevel = 1 diff --git a/src/realmd/AuthCodes.h b/src/realmd/AuthCodes.h index 731214f5a..514585c37 100644 --- a/src/realmd/AuthCodes.h +++ b/src/realmd/AuthCodes.h @@ -66,8 +66,8 @@ enum LoginResult // 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 and WoW:TBC 3.0.3 client build 9149, 9155... +// will only support WoW and WoW:TBC 3.0.3 client build 9149, 9155, 9183... -#define EXPECTED_MANGOS_CLIENT_BUILD {9149, 9155, 0} +#define EXPECTED_MANGOS_CLIENT_BUILD {9149, 9155, 9183, 0} #endif From d48844a699dd97e130e31b41d506a68b3e098980 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 5 Nov 2008 21:47:56 +0300 Subject: [PATCH 073/256] More work on pet spells, typo fix --- src/game/MiscHandler.cpp | 4 ++ src/game/Pet.cpp | 64 ++++++++++------- src/game/Pet.h | 5 +- src/game/PetHandler.cpp | 6 +- src/game/Player.cpp | 151 ++++++++++++++++++--------------------- src/game/QuestDef.cpp | 2 +- src/game/Unit.cpp | 8 +-- src/game/Unit.h | 27 ++++--- src/game/UpdateFields.h | 2 +- 9 files changed, 146 insertions(+), 123 deletions(-) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 80bf07564..c0cb648f4 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -892,6 +892,8 @@ void WorldSession::HandleUpdateAccountData(WorldPacket &recv_data) 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; @@ -943,6 +945,8 @@ void WorldSession::HandleRequestAccountData(WorldPacket& recv_data) uint32 type; recv_data >> type; + sLog.outDebug("RAD: type %u", type); + if(type > NUM_ACCOUNT_DATA_TYPES) return; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 56ab76c30..ca6696832 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -56,6 +56,8 @@ Pet::Pet(PetType type) : Creature() m_auraUpdateMask = 0; + m_loading = false; + // pets always have a charminfo, even if they are not actually charmed CharmInfo* charmInfo = InitCharmInfo(this); @@ -101,6 +103,8 @@ void Pet::RemoveFromWorld() bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool current ) { + m_loading = true; + uint32 ownerid = owner->GetGUIDLow(); QueryResult *result; @@ -341,6 +345,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu } } + m_loading = false; return true; } @@ -1277,7 +1282,8 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s ToggleAutocast(itr->first, false); oldspell_id = itr->first; - removeSpell(itr->first); + //removeSpell(itr->first); + unlearnSpell(itr->first); break; } } @@ -1299,16 +1305,6 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s newspell->slotId = tmpslot; m_spells[spell_id] = newspell; - if(GetOwner()->GetTypeId() == TYPEID_PLAYER) - { - if(!IsPassiveSpell(spell_id)) - { - WorldPacket data(SMSG_PET_LEARNED_SPELL, 2); - data << uint16(spell_id); - ((Player*)GetOwner())->GetSession()->SendPacket(&data); - } - } - if (IsPassiveSpell(spell_id)) CastSpell(this, spell_id, true); else if(state == PETSPELL_NEW) @@ -1326,6 +1322,16 @@ bool Pet::learnSpell(uint16 spell_id) if (!addSpell(spell_id)) return false; + if(GetOwner()->GetTypeId() == TYPEID_PLAYER) + { + if(!m_loading) + { + WorldPacket data(SMSG_PET_LEARNED_SPELL, 2); + data << uint16(spell_id); + ((Player*)GetOwner())->GetSession()->SendPacket(&data); + } + } + Unit* owner = GetOwner(); if(owner->GetTypeId() == TYPEID_PLAYER) ((Player*)owner)->PetSpellInitialize(); @@ -1343,18 +1349,36 @@ void Pet::learnLevelupSpells() if(itr->ReqLevel <= getLevel()) learnSpell(itr->SpellId); else - removeSpell(itr->SpellId); + unlearnSpell(itr->SpellId); } } -void Pet::removeSpell(uint16 spell_id) +bool Pet::unlearnSpell(uint16 spell_id) +{ + if(removeSpell(spell_id)) + { + if(GetOwner()->GetTypeId() == TYPEID_PLAYER) + { + if(!m_loading) + { + WorldPacket data(SMSG_PET_UNLEARNED_SPELL, 2); + data << uint16(spell_id); + ((Player*)GetOwner())->GetSession()->SendPacket(&data); + } + } + return true; + } + return false; +} + +bool Pet::removeSpell(uint16 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) { @@ -1366,15 +1390,7 @@ void Pet::removeSpell(uint16 spell_id) RemoveAurasDueToSpell(spell_id); - if(GetOwner()->GetTypeId() == TYPEID_PLAYER) - { - if(!IsPassiveSpell(spell_id)) - { - WorldPacket data(SMSG_PET_UNLEARNED_SPELL, 2); - data << uint16(spell_id); - ((Player*)GetOwner())->GetSession()->SendPacket(&data); - } - } + return true; } bool Pet::_removeSpell(uint16 spell_id) diff --git a/src/game/Pet.h b/src/game/Pet.h index cbabb3985..992396e7b 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -68,6 +68,7 @@ struct PetSpell { uint16 slotId; uint16 active; + PetSpellState state : 16; PetSpellType type : 16; }; @@ -191,7 +192,8 @@ class Pet : public Creature 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 learnLevelupSpells(); - void removeSpell(uint16 spell_id); + bool unlearnSpell(uint16 spell_id); + bool removeSpell(uint16 spell_id); bool _removeSpell(uint16 spell_id); PetSpellMap m_spells; @@ -222,6 +224,7 @@ class Pet : public Creature int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets) int32 m_bonusdamage; uint64 m_auraUpdateMask; + bool m_loading; DeclinedName *m_declinedname; diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index 511544afe..d02080ccb 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -155,7 +155,6 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) } break; case ACT_DISABLED: //0x8100 spell (disabled), ignore - case ACT_CAST: //0x0100 case ACT_ENABLED: //0xc100 spell { Unit* unit_target; @@ -349,7 +348,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) && spell_id && !pet->HasSpell(spell_id))) { //sign for autocast if(act_state == ACT_ENABLED && spell_id) @@ -519,7 +518,8 @@ void WorldSession::HandlePetUnlearnOpcode(WorldPacket& recvPacket) { uint32 spell_id = itr->first; // Pet::removeSpell can invalidate iterator at erase NEW spell ++itr; - pet->removeSpell(spell_id); + //pet->removeSpell(spell_id); + pet->unlearnSpell(spell_id); } for(uint8 i = 0; i < 10; i++) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 4ee84ebc9..374138b42 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2341,7 +2341,6 @@ void Player::SendInitialSpells() continue; data << uint16(itr->first); - //data << uint16(itr->second->slotId); data << uint16(0); // it's not slot id spellCount +=1; @@ -2368,13 +2367,13 @@ void Player::SendInitialSpells() data << uint16(sEntry->Category); // spell category if(sEntry->Category) // may be wrong, but anyway better than nothing... { - data << uint32(0); - data << uint32(cooldown); + data << uint32(0); // cooldown + data << uint32(cooldown); // category cooldown } else { - data << uint32(cooldown); - data << uint32(0); + data << uint32(cooldown); // cooldown + data << uint32(0); // category cooldown } } @@ -16002,68 +16001,67 @@ void Player::PetSpellInitialize() { Pet* pet = GetPet(); - if(pet) + if(!pet) + return; + + sLog.outDebug("Pet Spells Groups"); + + CharmInfo *charmInfo = pet->GetCharmInfo(); + + 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); + + // action bar loop + for(uint32 i = 0; i < 10; i++) { - uint8 addlist = 0; - - sLog.outDebug("Pet Spells Groups"); - - CreatureInfo const *cinfo = pet->GetCreatureInfo(); - - 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; - } - } - - // first line + actionbar + spellcount + spells + last adds - WorldPacket data(SMSG_PET_SPELLS, 16+40+1+4*addlist+25); - - CharmInfo *charmInfo = pet->GetCharmInfo(); - - //16 - data << uint64(pet->GetGUID()); - data << uint32(pet->GetCreatureInfo()->family); // creature family (required for pet talents) - data << uint8(charmInfo->GetReactState()) << uint8(charmInfo->GetCommandState()) << uint16(0); - data << uint32(0); - - for(uint32 i = 0; i < 10; i++) //40 - { - data << uint16(charmInfo->GetActionBarEntry(i)->SpellOrAction) << uint16(charmInfo->GetActionBarEntry(i)->Type); - } - - data << uint8(addlist); //1 - - 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; - - data << uint16(itr->first); - data << uint16(itr->second->active); // pet spell active state isn't boolean - } - } - - //data << uint8(0x01) << uint32(0x6010) << uint32(0x01) << uint32(0x05) << uint16(0x00); //15 - uint8 count = 3; //1+8+8+8=25 - - // 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 - - GetSession()->SendPacket(&data); + data << uint32(charmInfo->GetActionBarEntry(i)->Raw); } + + size_t spellsCountPos = data.wpos(); + + // spells count + uint8 addlist = 0; + data << uint8(addlist); // placeholder + + 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) + { + 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.put(spellsCountPos, addlist); + + uint8 cooldownsCount = pet->m_CreatureSpellCooldowns.size() + pet->m_CreatureCategoryCooldowns.size(); + data << uint8(cooldownsCount); + + for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureSpellCooldowns.begin(); itr != pet->m_CreatureSpellCooldowns.end(); ++itr) + { + data << uint16(itr->first); // spellid + data << uint16(0); // unk + 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) + { + data << uint16(itr->first); // spellid + data << uint16(0); // unk + data << uint32(0); // cooldown + data << uint32(itr->second); // category cooldown + } + + GetSession()->SendPacket(&data); } void Player::PossessSpellInitialize() @@ -16087,8 +16085,8 @@ void Player::PossessSpellInitialize() //16 data << uint64(charm->GetGUID()); data << uint32(0x00000000); - data << uint8(0) << uint8(0) << uint16(0); data << uint32(0); + data << uint8(0) << uint8(0) << uint16(0); for(uint32 i = 0; i < 10; i++) //40 { @@ -16097,11 +16095,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); } @@ -16138,15 +16133,14 @@ 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); - data << uint32(0); for(uint32 i = 0; i < 10; i++) //40 { @@ -16168,11 +16162,8 @@ 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); } diff --git a/src/game/QuestDef.cpp b/src/game/QuestDef.cpp index a8f903bf7..1e2cd6021 100644 --- a/src/game/QuestDef.cpp +++ b/src/game/QuestDef.cpp @@ -65,7 +65,7 @@ Quest::Quest(Field * questRecord) ReqItemId[i] = questRecord[39+i].GetUInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ReqItemCount[i] = questRecord[42+i].GetUInt32(); + ReqItemCount[i] = questRecord[43+i].GetUInt32(); for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) ReqSourceId[i] = questRecord[47+i].GetUInt32(); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 8b894bb87..415f6a7a3 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9897,7 +9897,7 @@ void CharmInfo::InitEmptyActionBar() { for(uint32 x = 1; x < 10; ++x) { - PetActionBar[x].Type = ACT_CAST; + PetActionBar[x].Type = ACT_ENABLED; PetActionBar[x].SpellOrAction = 0; } PetActionBar[0].Type = ACT_COMMAND; @@ -9916,7 +9916,7 @@ void CharmInfo::InitPossessCreateSpells() 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_CAST); + AddSpellToAB(0, ((Creature*)m_unit)->m_spells[x], ACT_ENABLED); } } @@ -9959,7 +9959,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_ENABLED; AddSpellToAB(0, spellId, newstate); } @@ -9970,7 +9970,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].SpellOrAction == oldid) { PetActionBar[i].SpellOrAction = newid; if(!oldid) diff --git a/src/game/Unit.h b/src/game/Unit.h index e3ef72b73..824e530b3 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -593,8 +593,18 @@ struct CleanDamage struct UnitActionBarEntry { - uint32 Type; - uint32 SpellOrAction; + union + { + struct + { + uint16 Type; + uint16 SpellOrAction; + }; + struct + { + uint32 Raw; + }; + }; }; #define MAX_DECLINED_NAME_CASES 5 @@ -616,13 +626,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 diff --git a/src/game/UpdateFields.h b/src/game/UpdateFields.h index c5a8af86d..09953bea5 100644 --- a/src/game/UpdateFields.h +++ b/src/game/UpdateFields.h @@ -19,7 +19,7 @@ #ifndef _UPDATEFIELDS_AUTO_H #define _UPDATEFIELDS_AUTO_H -// Auto generated for version 3, 0, 3, 9155 +// Auto generated for version 3, 0, 3, 9183 enum EObjectFields { From 3f1da2602eb650500cdee35177c82db2089956aa Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 5 Nov 2008 22:02:16 +0300 Subject: [PATCH 074/256] Small fix --- src/game/Player.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 374138b42..d3938c37e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -16045,18 +16045,30 @@ void Player::PetSpellInitialize() uint8 cooldownsCount = pet->m_CreatureSpellCooldowns.size() + pet->m_CreatureCategoryCooldowns.size(); data << uint8(cooldownsCount); + time_t curTime = time(NULL); + for(CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureSpellCooldowns.begin(); itr != pet->m_CreatureSpellCooldowns.end(); ++itr) { + time_t cooldown = 0; + + if(itr->second > curTime) + cooldown = (itr->second - curTime) * 1000; + data << uint16(itr->first); // spellid - data << uint16(0); // unk + 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); // unk + data << uint16(0); // spell category? data << uint32(0); // cooldown data << uint32(itr->second); // category cooldown } From cdd1f4e098b0d79ef2998a3d33a9cb56ccd9ceb8 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 5 Nov 2008 23:08:23 +0300 Subject: [PATCH 075/256] Client crash fix --- src/game/Unit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/Unit.h b/src/game/Unit.h index 824e530b3..de5d6f1b3 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -597,8 +597,8 @@ struct UnitActionBarEntry { struct { - uint16 Type; uint16 SpellOrAction; + uint16 Type; }; struct { From ca8180ecd1c308776efd4749d5172ec4943d8901 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Thu, 6 Nov 2008 13:22:43 +0300 Subject: [PATCH 076/256] Futher pet spell work --- src/game/Pet.cpp | 13 +++++++------ src/game/PetHandler.cpp | 7 ++++--- src/game/SpellMgr.cpp | 6 +----- src/game/SpellMgr.h | 12 +++--------- src/game/Unit.cpp | 8 ++++---- 5 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index ca6696832..6c88b614b 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -1282,7 +1282,6 @@ bool Pet::addSpell(uint16 spell_id, uint16 active, PetSpellState state, uint16 s ToggleAutocast(itr->first, false); oldspell_id = itr->first; - //removeSpell(itr->first); unlearnSpell(itr->first); break; } @@ -1340,16 +1339,18 @@ bool Pet::learnSpell(uint16 spell_id) void Pet::learnLevelupSpells() { - PetLevelupSpellList const *levelupSpells = spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family); + PetLevelupSpellSet const *levelupSpells = spellmgr.GetPetLevelupSpellList(GetCreatureInfo()->family); if(!levelupSpells) return; - for(PetLevelupSpellList::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr) + uint32 level = getLevel(); + + for(PetLevelupSpellSet::const_iterator itr = levelupSpells->begin(); itr != levelupSpells->end(); ++itr) { - if(itr->ReqLevel <= getLevel()) - learnSpell(itr->SpellId); + if(itr->first <= level) + learnSpell(itr->second); else - unlearnSpell(itr->SpellId); + unlearnSpell(itr->second); } } diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index d02080ccb..8c2359322 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -154,8 +154,9 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) break; } break; - case ACT_DISABLED: //0x8100 spell (disabled), ignore - 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) @@ -348,7 +349,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) && 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) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index afb98e34b..02e2cdfa1 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1970,7 +1970,6 @@ void SpellMgr::LoadSpellPetAuras() void SpellMgr::LoadPetLevelupSpellMap() { - PetLevelupSpell petSpell; CreatureFamilyEntry const *creatureFamily; SpellEntry const *spell; uint32 count = 0; @@ -2140,10 +2139,7 @@ void SpellMgr::LoadPetLevelupSpellMap() } } - petSpell.SpellId = spell->Id; - petSpell.ReqLevel = spell->spellLevel; - - mPetLevelupSpellMap[creatureFamily->ID].push_back(petSpell); + mPetLevelupSpellMap[creatureFamily->ID][spell->spellLevel] = spell->Id; count++; } } diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 87bcdb339..131da2a1f 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -626,14 +626,8 @@ typedef std::multimap SpellLearnSpellMap; typedef std::multimap SkillLineAbilityMap; -struct PetLevelupSpell -{ - uint32 SpellId; - uint32 ReqLevel; -}; - -typedef std::vector PetLevelupSpellList; -typedef std::map PetLevelupSpellMap; +typedef std::map PetLevelupSpellSet; +typedef std::map PetLevelupSpellMap; inline bool IsPrimaryProfessionSkill(uint32 skill) { @@ -850,7 +844,7 @@ class SpellMgr return NULL; } - PetLevelupSpellList const* GetPetLevelupSpellList(uint32 petFamily) const + PetLevelupSpellSet const* GetPetLevelupSpellList(uint32 petFamily) const { PetLevelupSpellMap::const_iterator itr = mPetLevelupSpellMap.find(petFamily); if(itr != mPetLevelupSpellMap.end()) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 415f6a7a3..808a69f01 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9897,7 +9897,7 @@ void CharmInfo::InitEmptyActionBar() { for(uint32 x = 1; x < 10; ++x) { - PetActionBar[x].Type = ACT_ENABLED; + PetActionBar[x].Type = ACT_PASSIVE; PetActionBar[x].SpellOrAction = 0; } PetActionBar[0].Type = ACT_COMMAND; @@ -9916,7 +9916,7 @@ void CharmInfo::InitPossessCreateSpells() 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_ENABLED); + AddSpellToAB(0, ((Creature*)m_unit)->m_spells[x], ACT_PASSIVE); } } @@ -9959,7 +9959,7 @@ void CharmInfo::InitCharmCreateSpells() if(onlyselfcast || !IsPositiveSpell(spellId)) //only self cast and spells versus enemies are autocastable newstate = ACT_DISABLED; else - newstate = ACT_ENABLED; + newstate = ACT_PASSIVE; AddSpellToAB(0, spellId, newstate); } @@ -9970,7 +9970,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].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) From d7f8a60835cf84f3ca167cd134cdb39719949e17 Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 7 Nov 2008 16:19:49 +0100 Subject: [PATCH 077/256] Implemented ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM and ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM Fixed CMSG_CANCEL_CAST opcode --- src/game/AchievementMgr.cpp | 18 ++++++++++++++++++ src/game/LootHandler.cpp | 2 ++ src/game/MiscHandler.cpp | 2 +- src/game/Player.cpp | 1 + src/game/SpellHandler.cpp | 5 ++++- 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 690ea9dc3..6e4dfa324 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -321,6 +321,20 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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; } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); @@ -395,6 +409,10 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: diff --git a/src/game/LootHandler.cpp b/src/game/LootHandler.cpp index e478b0e7d..f9c26fd29 100644 --- a/src/game/LootHandler.cpp +++ b/src/game/LootHandler.cpp @@ -142,6 +142,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 ); @@ -483,6 +484,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/MiscHandler.cpp b/src/game/MiscHandler.cpp index c0cb648f4..21e4712a8 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1672,7 +1672,7 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data ) void WorldSession::HandleInspectAchievements( WorldPacket & recv_data ) { - sLog.outString("WorldSession::HandleInspectAchievements"); + CHECK_PACKET_SIZE(recv_data, 1); uint64 guid; if(!readGUID(recv_data, guid)) return; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a67909329..e65597604 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -13054,6 +13054,7 @@ void Player::ItemAddedQuestCheck( uint32 entry, uint32 count ) } } UpdateForQuestsGO(); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, entry); } void Player::ItemRemovedQuestCheck( uint32 entry, uint32 count ) diff --git a/src/game/SpellHandler.cpp b/src/game/SpellHandler.cpp index c8f41227d..2221c26b4 100644 --- a/src/game/SpellHandler.cpp +++ b/src/game/SpellHandler.cpp @@ -332,9 +332,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 From 7c73afbd228b1a0a8bae98282dbf529fd8d5cd1f Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 8 Nov 2008 16:44:10 +0300 Subject: [PATCH 078/256] Raid wide auras, untested --- src/game/SharedDefines.h | 3 +- src/game/SpellAuraDefines.h | 1 + src/game/SpellAuras.cpp | 58 +++++++++++++++++++++++++++++++++++++ src/game/SpellEffects.cpp | 2 +- src/game/SpellMgr.cpp | 9 +++--- src/game/SpellMgr.h | 1 + src/realmd/AuthCodes.h | 4 +-- 7 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 54f06411e..50164f47f 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -556,7 +556,6 @@ enum SpellEffects SPELL_EFFECT_TRADE_SKILL = 47, SPELL_EFFECT_STEALTH = 48, SPELL_EFFECT_DETECT = 49, - // SPELL_EFFECT_SUMMON_OBJECT = 50, SPELL_EFFECT_TRANS_DOOR = 50, SPELL_EFFECT_FORCE_CRITICAL_HIT = 51, SPELL_EFFECT_GUARANTEE_HIT = 52, @@ -572,7 +571,7 @@ enum SpellEffects SPELL_EFFECT_POWER_BURN = 62, SPELL_EFFECT_THREAT = 63, SPELL_EFFECT_TRIGGER_SPELL = 64, - SPELL_EFFECT_HEALTH_FUNNEL = 65, + SPELL_EFFECT_APPLY_AREA_AURA_RAID = 65, SPELL_EFFECT_POWER_FUNNEL = 66, SPELL_EFFECT_HEAL_MAX_HEALTH = 67, SPELL_EFFECT_INTERRUPT_CAST = 68, diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 2a857ea3c..977bceb93 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -336,6 +336,7 @@ enum AuraType 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 82ea197ab..a7e2ff69f 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -452,6 +452,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; @@ -682,6 +687,41 @@ void AreaAura::Update(uint32 diff) } break; } + case AREA_AURA_RAID: + { + Group *pGroup = NULL; + + if (owner->GetTypeId() == TYPEID_PLAYER) + pGroup = ((Player*)owner)->GetGroup(); + + if( pGroup) + { + uint8 subgroup = ((Player*)owner)->GetSubGroup(); + for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* Target = itr->getSource(); + if(Target && Target->isAlive() && caster->IsFriendlyTo(Target)) + { + if(caster->IsWithinDistInMap(Target, m_radius)) + targets.push_back(Target); + Pet *pet = Target->GetPet(); + if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius)) + targets.push_back(pet); + } + } + } + else + { + // add owner + if( owner != caster && caster->IsWithinDistInMap(owner, m_radius) ) + targets.push_back(owner); + // add caster's pet + Unit* pet = caster->GetPet(); + if( pet && caster->IsWithinDistInMap(pet, m_radius)) + targets.push_back(pet); + } + break; + } case AREA_AURA_FRIEND: { CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY())); @@ -781,6 +821,24 @@ void AreaAura::Update(uint32 diff) tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); } } + else if( m_areaAuraType == AREA_AURA_RAID) // TODO: fix me! + { + // not check group if target == owner or target == pet + if (caster->GetCharmerOrOwnerGUID() != tmp_target->GetGUID() && caster->GetGUID() != tmp_target->GetCharmerOrOwnerGUID()) + { + Player* check = caster->GetCharmerOrOwnerPlayerOrPlayerItself(); + + Group *pGroup = check ? check->GetGroup() : NULL; + if( pGroup ) + { + Player* checkTarget = tmp_target->GetCharmerOrOwnerPlayerOrPlayerItself(); + if(!checkTarget) + tmp_target->RemoveAura(tmp_spellId, tmp_effIndex); + } + else + 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() ) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 21a4a820e..1ccece6e4 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -121,7 +121,7 @@ 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::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID &Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused &Spell::EffectHealMaxHealth, // 67 SPELL_EFFECT_HEAL_MAX_HEALTH &Spell::EffectInterruptCast, // 68 SPELL_EFFECT_INTERRUPT_CAST diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 6f7feaa48..7bfbff618 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -182,10 +182,10 @@ SpellSpecific GetSpellSpecific(uint32 spellId) if ((spellInfo->SpellFamilyFlags & 0x00000820180400LL) && (spellInfo->AttributesEx3 & 0x200)) return SPELL_JUDGEMENT; - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) // TODO: fix it for WotLK!!! { // only paladin auras have this - if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY) + if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID) return SPELL_AURA; } break; @@ -1007,7 +1007,7 @@ bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo) { // Paladin aura Spell if(spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN - && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY) + && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_RAID) return false; // Druid form Spell if(spellInfo->SpellFamilyName == SPELLFAMILY_DRUID @@ -1424,7 +1424,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; diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 131da2a1f..df34a35a4 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -377,6 +377,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 || diff --git a/src/realmd/AuthCodes.h b/src/realmd/AuthCodes.h index 514585c37..53e77ee18 100644 --- a/src/realmd/AuthCodes.h +++ b/src/realmd/AuthCodes.h @@ -66,8 +66,8 @@ enum LoginResult // 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 and WoW:TBC 3.0.3 client build 9149, 9155, 9183... +// will only support WoW and WoW:TBC 3.0.3 client build 9155, 9174, 9183... -#define EXPECTED_MANGOS_CLIENT_BUILD {9149, 9155, 9183, 0} +#define EXPECTED_MANGOS_CLIENT_BUILD {9155, 9174, 9183, 0} #endif From 0a783585e0870c08e92235feca20c80d4c9c91dd Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 8 Nov 2008 17:48:42 +0300 Subject: [PATCH 079/256] Compile fix --- src/game/AchievementMgr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index 4a86277d6..397cf6cd7 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -36,8 +36,8 @@ struct CriteriaProgress time_t date; }; -typedef HM_NAMESPACE::hash_map CriteriaProgressMap; -typedef HM_NAMESPACE::hash_map CompletedAchievementMap; +typedef UNORDERED_MAP CriteriaProgressMap; +typedef UNORDERED_MAP CompletedAchievementMap; class Player; class WorldPacket; From eb0cfe7fec041a58f98d6bc4832b136ffe97175d Mon Sep 17 00:00:00 2001 From: arrai Date: Sat, 8 Nov 2008 16:26:00 +0100 Subject: [PATCH 080/256] Fixed ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING by using total fall distance instead of fall time. This distance might be used for a more accurate fall damage formula in a later version. --- src/game/AchievementMgr.cpp | 5 ++--- src/game/MovementHandler.cpp | 11 +++++++++-- src/game/Player.h | 1 + 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 6e4dfa324..c0f5da462 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -304,9 +304,8 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if(!gameeventmgr.IsActiveEvent(26)) continue; } - // miscvalue1 is falltime, calculate to fall height format given in dbc - uint32 fallHeight = uint32(0.06f*miscvalue1-91.5)*100; - SetCriteriaProgress(achievementCriteria, fallHeight); + // miscvalue1 is the ingame fallheight*100 as stored in dbc + SetCriteriaProgress(achievementCriteria, miscvalue1); break; } case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 426c070ef..0303a7dff 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -291,6 +291,10 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) // 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()) { + // calculate total z distance of the fall + // it is currently only used for the achievement system. It might be used in a more correct falldamage formula later + float z_diff = GetPlayer()->m_fallMovementInfo.z - movementInfo.z; + sLog.outDebug("zDiff = %f", z_diff); Player *target = GetPlayer(); //Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored @@ -323,8 +327,9 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) target->EnvironmentalDamage(target->GetGUID(), DAMAGE_FALL, damage); - if(target->isAlive()) - target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, movementInfo.fallTime); + // recheck alive, might have died of EnvironmentalDamage + if (target->isAlive()) + target->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, uint32(z_diff*100)); } //Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction @@ -363,6 +368,8 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) GetPlayer()->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); GetPlayer()->m_movementInfo = movementInfo; + if (GetPlayer()->m_fallMovementInfo.fallTime >= movementInfo.fallTime || GetPlayer()->m_fallMovementInfo.z <=movementInfo.z) + GetPlayer()->m_fallMovementInfo = movementInfo; if(GetPlayer()->isMovingOrTurning()) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); diff --git a/src/game/Player.h b/src/game/Player.h index 54f0d15ed..1e67267bf 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1945,6 +1945,7 @@ class MANGOS_DLL_SPEC Player : public Unit /*** VARIOUS SYSTEMS ***/ /*********************************************************/ MovementInfo m_movementInfo; + MovementInfo m_fallMovementInfo; bool isMoving() const { return HasUnitMovementFlag(movementFlagsMask); } bool isMovingOrTurning() const { return HasUnitMovementFlag(movementOrTurningFlagsMask); } From f6ff7b5a4597d15dc8ebd8f5792ba4ba5b2c6144 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 9 Nov 2008 01:41:26 +0300 Subject: [PATCH 081/256] Updated some enums --- src/game/ObjectMgr.cpp | 4 +- src/game/Player.cpp | 18 +++-- src/game/Player.h | 4 +- src/game/SharedDefines.h | 108 ++++++++++++++++++----------- src/game/SpellAuras.cpp | 34 ++++----- src/game/SpellEffects.cpp | 10 +-- src/game/StatSystem.cpp | 1 + src/shared/Database/DBCStructure.h | 2 +- 8 files changed, 107 insertions(+), 74 deletions(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 6f18cfacc..8c5986394 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -6719,7 +6719,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; @@ -6734,7 +6734,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; } } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 444785e11..7323f45da 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -127,7 +127,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) @@ -144,6 +144,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)) { @@ -796,7 +803,7 @@ void Player::HandleDrowning() m_isunderwater|= 0x04; StartMirrorTimer(BREATH_TIMER, UnderWaterTime); } - //continius trigger drowning "Damage" + //continuous trigger drowning "Damage" if ((m_breathTimer == 0) && (m_isunderwater & 0x01)) { //TODO: Check this formula @@ -918,7 +925,7 @@ void Player::SetDrunkValue(uint16 newDrunkenValue, uint32 itemId) return; WorldPacket data(SMSG_CROSSED_INEBRIATION_THRESHOLD, (8+4+4)); - data << GetGUID(); + data << uint64(GetGUID()); data << uint32(newDrunkenState); data << uint32(itemId); @@ -2736,8 +2743,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,8 +2924,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 ) { @@ -4646,6 +4649,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) diff --git a/src/game/Player.h b/src/game/Player.h index 1e67267bf..4646235f2 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -862,7 +862,7 @@ class MANGOS_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); @@ -972,7 +972,7 @@ class MANGOS_DLL_SPEC Player : public Unit 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 const& nodes, uint32 mount_id = 0 , Creature* npc = NULL); // mount_id can be used in scripting calls bool isAcceptTickets() const { return GetSession()->GetSecurity() >= SEC_GAMEMASTER && (m_ExtraFlags & PLAYER_EXTRA_GM_ACCEPT_TICKETS); } diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 50164f47f..24042c31a 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -702,11 +702,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, @@ -722,7 +722,7 @@ enum Mechanics MECHANIC_SHIELD = 19, MECHANIC_SHACKLE = 20, MECHANIC_MOUNT = 21, - MECHANIC_PERSUADE = 22, //0 spells use this mechanic + MECHANIC_INFECTED = 22, //0 spells use this mechanic MECHANIC_TURN = 23, MECHANIC_HORROR = 24, MECHANIC_INVULNERABILITY = 25, @@ -730,12 +730,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< Date: Sat, 8 Nov 2008 23:07:39 +0100 Subject: [PATCH 082/256] Implemented some spell achievements --- src/game/AchievementMgr.cpp | 106 ++++++++++++++++++++++++++++- src/game/AchievementMgr.h | 21 +++++- src/game/Spell.cpp | 20 +++++- src/shared/Database/DBCStructure.h | 8 +-- 4 files changed, 142 insertions(+), 13 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index c0f5da462..fea132cbe 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -27,6 +27,61 @@ #include "GameEvent.h" #include "World.h" +const CriteriaCastSpellRequirement* AchievementMgr::criteriaCastSpellRequirements[] = + { + new CriteriaCastSpellRequirement(5272, 3057, 0, 0), + new CriteriaCastSpellRequirement(5273, 2784, 0, 0), + new CriteriaCastSpellRequirement(5752, 9099, 0, 0), + new CriteriaCastSpellRequirement(5753, 8403, 0, 0), + + new CriteriaCastSpellRequirement(5772, 0, 0, RACE_GNOME), + new CriteriaCastSpellRequirement(5774, 0, 0, RACE_BLOODELF), + new CriteriaCastSpellRequirement(5775, 0, 0, RACE_DRAENEI), + new CriteriaCastSpellRequirement(5776, 0, 0, RACE_DWARF), + new CriteriaCastSpellRequirement(5777, 0, 0, RACE_HUMAN), + new CriteriaCastSpellRequirement(5778, 0, 0, RACE_NIGHTELF), + new CriteriaCastSpellRequirement(5779, 0, 0, RACE_ORC), + new CriteriaCastSpellRequirement(5780, 0, 0, RACE_TAUREN), + new CriteriaCastSpellRequirement(5781, 0, 0, RACE_TROLL), + new CriteriaCastSpellRequirement(5782, 0, 0, RACE_UNDEAD_PLAYER), + + new CriteriaCastSpellRequirement(6225, 5661, 0, 0), + new CriteriaCastSpellRequirement(6226, 26044, 0, 0), + new CriteriaCastSpellRequirement(6228, 739, 0, 0), + new CriteriaCastSpellRequirement(6229, 927, 0, 0), + new CriteriaCastSpellRequirement(6230, 1444, 0, 0), + new CriteriaCastSpellRequirement(6231, 8140, 0, 0), + new CriteriaCastSpellRequirement(6232, 5489, 0, 0), + new CriteriaCastSpellRequirement(6233,12336, 0, 0), + new CriteriaCastSpellRequirement(6234, 1351, 0, 0), + new CriteriaCastSpellRequirement(6235, 5484, 0, 0), + new CriteriaCastSpellRequirement(6236, 1182, 0, 0), + + new CriteriaCastSpellRequirement(6237, 0, CLASS_DEATH_KNIGHT, RACE_ORC), + new CriteriaCastSpellRequirement(6238, 0, CLASS_WARRIOR, RACE_HUMAN), + new CriteriaCastSpellRequirement(6239, 0, CLASS_SHAMAN, RACE_TAUREN), + new CriteriaCastSpellRequirement(6240, 0, CLASS_DRUID, RACE_NIGHTELF), + new CriteriaCastSpellRequirement(6241, 0, CLASS_ROGUE, RACE_UNDEAD_PLAYER), + new CriteriaCastSpellRequirement(6242, 0, CLASS_HUNTER, RACE_TROLL), + new CriteriaCastSpellRequirement(6243, 0, CLASS_MAGE, RACE_GNOME), + new CriteriaCastSpellRequirement(6244, 0, CLASS_PALADIN, RACE_DWARF), + new CriteriaCastSpellRequirement(6245, 0, CLASS_WARLOCK, RACE_BLOODELF), + new CriteriaCastSpellRequirement(6246, 0, CLASS_PRIEST, RACE_DRAENEI), + + new CriteriaCastSpellRequirement(6312, 0, CLASS_WARLOCK, RACE_GNOME), + new CriteriaCastSpellRequirement(6313, 0, CLASS_DEATH_KNIGHT, RACE_HUMAN), + new CriteriaCastSpellRequirement(6314, 0, CLASS_PRIEST, RACE_NIGHTELF), + new CriteriaCastSpellRequirement(6315, 0, CLASS_SHAMAN, RACE_ORC), + new CriteriaCastSpellRequirement(6316, 0, CLASS_DRUID, RACE_TAUREN), + new CriteriaCastSpellRequirement(6317, 0, CLASS_ROGUE, RACE_TROLL), + new CriteriaCastSpellRequirement(6318, 0, CLASS_WARRIOR, RACE_UNDEAD_PLAYER), + new CriteriaCastSpellRequirement(6319, 0, CLASS_MAGE, RACE_BLOODELF), + new CriteriaCastSpellRequirement(6320, 0, CLASS_PALADIN, RACE_DRAENEI), + new CriteriaCastSpellRequirement(6321, 0, CLASS_HUNTER, RACE_DWARF), + + new CriteriaCastSpellRequirement(6662, 31261, 0, 0), + NULL}; + AchievementMgr::AchievementMgr(Player *player) { m_player = player; @@ -187,7 +242,7 @@ void AchievementMgr::CheckAllAchievementCriteria() /** * this function will be called whenever the user might have done a criteria relevant action */ -void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, uint32 time) +void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1, uint32 miscvalue2, Unit *unit, uint32 time) { sLog.outString("AchievementMgr::UpdateAchievementCriteria(%u, %u, %u, %u)", type, miscvalue1, miscvalue2, time); AchievementCriteriaEntryList const& achievementCriteriaList = objmgr.GetAchievementCriteriaByType(type); @@ -334,11 +389,54 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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 + const CriteriaCastSpellRequirement *requirement = NULL; + + for (uint32 i=0; criteriaCastSpellRequirements[i]; i++) + { + if (criteriaCastSpellRequirements[i]->achievementCriteriaId == achievementCriteria->ID) + { + requirement = criteriaCastSpellRequirements[i]; + break; + } + } + + if (requirement) + { + 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; } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); } } + bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria) { AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementCriteria->referredAchievement); @@ -412,6 +510,12 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index 397cf6cd7..9edcf1cbe 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -36,9 +36,25 @@ struct CriteriaProgress time_t date; }; +struct CriteriaCastSpellRequirement +{ + CriteriaCastSpellRequirement(uint32 achievementCriteriaId, uint32 creatureEntry, uint32 playerClass, uint32 playerRace) + { + this->achievementCriteriaId = achievementCriteriaId; + this->creatureEntry = creatureEntry; + this->playerClass = playerClass; + this->playerRace = playerRace; + } + uint32 achievementCriteriaId; + uint32 creatureEntry; + uint8 playerClass; + uint8 playerRace; +}; + typedef UNORDERED_MAP CriteriaProgressMap; typedef UNORDERED_MAP CompletedAchievementMap; +class Unit; class Player; class WorldPacket; @@ -57,7 +73,7 @@ class AchievementMgr void LoadFromDB(QueryResult *achievementResult, QueryResult *criteriaResult); void SaveToDB(); - void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, uint32 time=0); + void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0); void CheckAllAchievementCriteria(); void SendAllAchievementData(); void SendRespondInspectAchievements(Player* player); @@ -76,7 +92,6 @@ class AchievementMgr Player* m_player; CriteriaProgressMap m_criteriaProgress; CompletedAchievementMap m_completedAchievements; - + static const CriteriaCastSpellRequirement* criteriaCastSpellRequirements[]; }; - #endif diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 0f3ca5801..7c073888d 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -959,6 +959,17 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) 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( !m_caster->IsFriendlyTo(unit) ) @@ -2081,8 +2092,13 @@ void Spell::cast(bool skipCheck) // set to real guid to be sent later to the client m_targets.updateTradeSlotItem(); - if(m_CastItem && m_caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_caster)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry()); + 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); + } // CAST SPELL SendSpellCooldown(); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 39b0b950e..136032a23 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -182,6 +182,7 @@ struct AchievementCriteriaEntry } be_spell_target; // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL= 29 + // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110 struct { uint32 spellID; // 3 @@ -422,13 +423,6 @@ struct AchievementCriteriaEntry uint32 lootTypeCount; // 4 } loot_type; - // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110 - struct - { - uint32 skillLine; // 3 - uint32 spellCount; // 4 - } cast_spell2; - // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE= 112 struct { From d2be8dbe8fb2ae95bfc402c1290d2417ffe65fb0 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 9 Nov 2008 03:46:47 +0300 Subject: [PATCH 083/256] Implement expansion class check and unique class limit. --- src/game/CharacterHandler.cpp | 61 +++++++++++++++++++++--------- src/shared/Database/DBCStructure.h | 9 +++-- src/shared/Database/DBCfmt.cpp | 2 +- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 2c3df86b0..d6a0c8a8e 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -228,17 +228,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; } @@ -309,25 +308,37 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); bool have_same_race = false; - if(!AllowTwoSideAccounts || skipCinematics == 1) + 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 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[0].GetUInt32(); + + if(class_ == CLASS_DEATH_KNIGHT) + { + uint8 acc_class = field[1].GetUInt32(); + if(acc_class == CLASS_DEATH_KNIGHT) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket( &data ); + return; + } + } // 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 ); @@ -336,15 +347,29 @@ 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[0].GetUInt32(); + + if(!have_same_race) + have_same_race = race_ == acc_race; + + if(class_ == CLASS_DEATH_KNIGHT) { - field = result2->Fetch(); - race = field[0].GetUInt32(); + uint8 acc_class = field[1].GetUInt32(); + if(acc_class == CLASS_DEATH_KNIGHT) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket( &data ); + return; + } } - have_same_race = race_ == race; } delete result2; } diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 136032a23..7d9aa109f 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -543,9 +543,9 @@ struct ChatChannelsEntry struct ChrClassesEntry { uint32 ClassID; // 0 - // 1-2, unused - uint32 powerType; // 3 - // 4, unused + // 1, unused + uint32 powerType; // 2 + // 3-4, unused //char* name[16]; // 5-20 unused // 21 string flag, unused //char* string1[16]; // 21-36 unused @@ -556,6 +556,7 @@ struct ChrClassesEntry uint32 spellfamily; // 56 // 57, unused uint32 CinematicSequence; // 58 id from CinematicSequences.dbc + uint32 addon; // 59 (0 - original race, 1 - tbc addon, ...) }; struct ChrRacesEntry @@ -961,7 +962,7 @@ struct ScalingStatValuesEntry struct SkillLineEntry { uint32 id; // 0 m_ID - int32 categoryId; // 1 m_categoryID (index from SkillLineCategory.dbc) + uint32 categoryId; // 1 m_categoryID (index from SkillLineCategory.dbc) //uint32 skillCostID; // 2 m_skillCostsID not used char* name[16]; // 3-18 m_displayName_lang // 19 string flags, not used diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index a80a94ace..aa2564ab8 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -26,7 +26,7 @@ const char BattlemasterListEntryfmt[]="niiiiiiiiiiiixxxssssssssssssssssxx"; const char CharTitlesEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx"; // ChatChannelsEntryfmt, index not used (more compact store) -const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixix"; +const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii"; const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxxxx"; const char CreatureFamilyfmt[]="nfifiiiiixssssssssssssssssxx"; From 90b0c47592dd279572180dc5d115f1ed8a3d5224 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 9 Nov 2008 11:39:01 +0300 Subject: [PATCH 084/256] uint->int --- src/shared/Database/DBCStructure.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 7d9aa109f..7937efdac 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -962,7 +962,7 @@ struct ScalingStatValuesEntry struct SkillLineEntry { uint32 id; // 0 m_ID - uint32 categoryId; // 1 m_categoryID (index from SkillLineCategory.dbc) + int32 categoryId; // 1 m_categoryID (index from SkillLineCategory.dbc) //uint32 skillCostID; // 2 m_skillCostsID not used char* name[16]; // 3-18 m_displayName_lang // 19 string flags, not used From 1d3667e7656fadb2cee2381662a9d5d9c1edc3e1 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 9 Nov 2008 18:47:26 +0300 Subject: [PATCH 085/256] Some work on visible auras --- src/game/CharacterHandler.cpp | 2 +- src/game/Chat.cpp | 2 +- src/game/Player.cpp | 49 ++++++++++++++++++++--------------- src/game/SpellAuraDefines.h | 10 +++---- src/game/SpellAuras.cpp | 25 ++++++------------ src/game/Unit.cpp | 2 -- src/game/Unit.h | 28 +++++++++++++++++--- 7 files changed, 66 insertions(+), 52 deletions(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index d6a0c8a8e..512848107 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -62,7 +62,7 @@ bool LoginQueryHolder::Initialize() 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 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,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_index,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u' ORDER by spell,effect_index", 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_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)); diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 3662ad4e0..d77838cfe 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -531,7 +531,7 @@ ChatCommand * ChatHandler::getCommandTable() { "cometome", SEC_ADMINISTRATOR, false, &ChatHandler::HandleComeToMeCommand, "", NULL }, { "damage", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDamageCommand, "", NULL }, { "combatstop", SEC_GAMEMASTER, false, &ChatHandler::HandleCombatStopCommand, "", NULL }, - { "chardelete", SEC_CONSOLE, true, &ChatHandler::HandleCombatStopCommand, "", NULL }, + { "chardelete", SEC_CONSOLE, true, &ChatHandler::HandleCharacterDeleteCommand, "", NULL }, { "sendmessage", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMessageCommand, "", NULL }, { "repairitems", SEC_GAMEMASTER, false, &ChatHandler::HandleRepairitemsCommand, "", NULL }, { "waterwalk", SEC_GAMEMASTER, false, &ChatHandler::HandleWaterwalkCommand, "", NULL }, diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 7323f45da..838e673d7 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17756,31 +17756,38 @@ void Player::SendAurasForTarget(Unit *target) WorldPacket data(SMSG_AURA_UPDATE_ALL); data.append(target->GetPackGUID()); - 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; - - data << uint8(aura->GetAuraSlot()); - data << uint32(aura->GetId()); - - if(aura->GetId()) + for(uint32 j = 0; j < 3; ++j) { - uint8 auraFlags = aura->GetAuraFlags(); - data << uint8(auraFlags); // flags - data << uint8(aura->GetAuraLevel()); // level - data << uint8(aura->m_procCharges); // charges - - /*if(!(auraFlags & AFLAG_NOT_GUID)) + if(Aura *aura = target->GetAura(itr->second, j)) { - data << uint8(0) // packed GUID of someone (caster?) - }*/ + data << uint8(aura->GetAuraSlot()); + data << uint32(aura->GetId()); - if(auraFlags & AFLAG_DURATION) // include aura duration - { - data << uint32(aura->GetAuraMaxDuration()); - data << uint32(aura->GetAuraDuration()); + if(aura->GetId()) + { + uint8 auraFlags = aura->GetAuraFlags(); + // flags + data << uint8(auraFlags); + // level + data << uint8(aura->GetAuraLevel()); + // charges + data << uint8(aura->m_procCharges); + + if(!(auraFlags & AFLAG_NOT_GUID)) + { + data << uint8(0); // packed GUID of someone (caster?) + } + + if(auraFlags & AFLAG_DURATION) // include aura duration + { + data << uint32(aura->GetAuraMaxDuration()); + data << uint32(aura->GetAuraDuration()); + } + } + break; } } } diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 977bceb93..47f1b28d0 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -18,8 +18,7 @@ #ifndef MANGOS_SPELLAURADEFINES_H #define MANGOS_SPELLAURADEFINES_H -#define MAX_AURAS 56 // probably changes to 64 in WotLK -#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 { @@ -27,14 +26,11 @@ enum AURA_FLAGS AFLAG_EFF_INDEX_0 = 0x01, AFLAG_EFF_INDEX_1 = 0x02, AFLAG_EFF_INDEX_2 = 0x04, - AFLAG_NOT_GUID = 0x08, + AFLAG_NOT_GUID = 0x08, // caster guid? AFLAG_UNK1 = 0x10, // positive? AFLAG_DURATION = 0x20, AFLAG_UNK2 = 0x40, - AFLAG_UNK3 = 0x80, - AFLAG_NEGATIVE = 0x09, - AFLAG_POSITIVE = 0x1F, - AFLAG_MASK = 0xFF + AFLAG_NEGATIVE = 0x80 }; //m_schoolAbsorb diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index c6acb80c4..81b883ae9 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -947,22 +947,13 @@ void Aura::_AddAura() { if(!samespell) // new slot need { - if (IsPositive()) // empty positive slot + if(m_target->GetVisibleAurasCount() < MAX_AURAS) { - for (uint8 i = 0; i < MAX_POSITIVE_AURAS; i++) + Unit::VisibleAuraMap const *visibleAuras = m_target->GetVisibleAuras(); + for(uint8 i = 0; i < MAX_AURAS; ++i) { - if (m_target->GetVisibleAura(i) == 0) - { - slot = i; - break; - } - } - } - else // empty negative slot - { - for (uint8 i = MAX_POSITIVE_AURAS; i < MAX_AURAS; i++) - { - if (m_target->GetVisibleAura(i) == 0) + Unit::VisibleAuraMap::const_iterator itr = visibleAuras->find(i); + if(itr == visibleAuras->end()) { slot = i; break; @@ -978,7 +969,7 @@ void Aura::_AddAura() if(slot < MAX_AURAS) // slot found { SetAura(false); - SetAuraFlags(AFLAG_EFF_INDEX_0 | AFLAG_NOT_GUID | (GetAuraMaxDuration() ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_UNK1 : AFLAG_NONE)); + SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_GUID | (GetAuraMaxDuration() ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_NONE : AFLAG_NEGATIVE)); SetAuraLevel(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); UpdateAuraCharges(); SendAuraUpdate(false); @@ -1135,10 +1126,10 @@ void Aura::SendAuraUpdate(bool remove) data << uint8(GetAuraLevel()); data << uint8(GetAuraCharges()); - /*if(!(auraFlags & AFLAG_NOT_GUID)) + if(!(auraFlags & AFLAG_NOT_GUID)) { data << uint8(0); // pguid - }*/ + } if(auraFlags & AFLAG_DURATION) { diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 5c3eadc8d..355e122ed 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -184,8 +184,6 @@ Unit::Unit() m_ShapeShiftFormSpellId = 0; m_canModifyStats = false; - for (int i = 0; i < MAX_AURAS; ++i) - m_visibleAuras[i] = 0; for (int i = 0; i < MAX_SPELL_IMMUNITY; i++) m_spellImmune[i].clear(); for (int i = 0; i < UNIT_MOD_END; i++) diff --git a/src/game/Unit.h b/src/game/Unit.h index 3dfcfdcb8..c766bea1e 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -716,6 +716,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject typedef std::list Diminishing; typedef std::set AuraTypeSet; typedef std::set ComboPointHolderSet; + typedef std::map VisibleAuraMap; virtual ~Unit ( ); @@ -1155,8 +1156,29 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void removeHatedBy(HostilReference* /*pHostilReference*/ ) { /* nothing to do yet */ } HostilRefManager& getHostilRefManager() { return m_HostilRefManager; } - uint32 GetVisibleAura(uint32 slot) { return m_visibleAuras[slot]; } - void SetVisibleAura(uint32 slot, uint32 spellid) { m_visibleAuras[slot] = spellid; } + uint32 GetVisibleAura(uint8 slot) + { + VisibleAuraMap::iterator itr = m_visibleAuras.find(slot); + if(itr != m_visibleAuras.end()) + return itr->second; + return 0; + } + void SetVisibleAura(uint8 slot, uint32 spellid) + { + if(spellid == 0) + { + VisibleAuraMap::iterator itr = m_visibleAuras.find(slot); + if(itr != m_visibleAuras.end()) + { + m_visibleAuras.erase(itr); + return; + } + } + else + m_visibleAuras[slot] = spellid; + } + VisibleAuraMap const *GetVisibleAuras() { return &m_visibleAuras; } + uint8 GetVisibleAurasCount() { return m_visibleAuras.size(); } Aura* GetAura(uint32 spellId, uint32 effindex); AuraMap & GetAuras() { return m_Auras; } @@ -1330,7 +1352,7 @@ class MANGOS_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 - uint32 m_visibleAuras[MAX_AURAS]; + VisibleAuraMap m_visibleAuras; float m_speed_rate[MAX_MOVE_TYPE]; From 2c1671ef5c482965663781bc6d1ea844364b734e Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 9 Nov 2008 19:53:24 +0300 Subject: [PATCH 086/256] Positive auras can be cancelled once again :) --- src/game/Player.cpp | 9 ++++++--- src/game/SpellAuraDefines.h | 4 ++-- src/game/SpellAuras.cpp | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 838e673d7..037a80080 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17753,6 +17753,9 @@ void Player::learnSkillRewardedSpells() void Player::SendAurasForTarget(Unit *target) { + if(target->GetVisibleAuras()->empty()) // speedup things + return; + WorldPacket data(SMSG_AURA_UPDATE_ALL); data.append(target->GetPackGUID()); @@ -17776,12 +17779,12 @@ void Player::SendAurasForTarget(Unit *target) // charges data << uint8(aura->m_procCharges); - if(!(auraFlags & AFLAG_NOT_GUID)) + if(!(auraFlags & AFLAG_NOT_CASTER)) { - data << uint8(0); // packed GUID of someone (caster?) + data << uint8(0); // packed GUID of someone (caster?) } - if(auraFlags & AFLAG_DURATION) // include aura duration + if(auraFlags & AFLAG_DURATION) // include aura duration { data << uint32(aura->GetAuraMaxDuration()); data << uint32(aura->GetAuraDuration()); diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 47f1b28d0..6d744df6b 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -26,8 +26,8 @@ enum AURA_FLAGS AFLAG_EFF_INDEX_0 = 0x01, AFLAG_EFF_INDEX_1 = 0x02, AFLAG_EFF_INDEX_2 = 0x04, - AFLAG_NOT_GUID = 0x08, // caster guid? - AFLAG_UNK1 = 0x10, // positive? + AFLAG_NOT_CASTER = 0x08, + AFLAG_POSITIVE = 0x10, AFLAG_DURATION = 0x20, AFLAG_UNK2 = 0x40, AFLAG_NEGATIVE = 0x80 diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 81b883ae9..1f5c5ff04 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -969,7 +969,7 @@ void Aura::_AddAura() if(slot < MAX_AURAS) // slot found { SetAura(false); - SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_GUID | (GetAuraMaxDuration() ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_NONE : AFLAG_NEGATIVE)); + SetAuraFlags((1 << GetEffIndex()) | AFLAG_NOT_CASTER | ((GetAuraMaxDuration() > 0) ? AFLAG_DURATION : AFLAG_NONE) | (IsPositive() ? AFLAG_POSITIVE : AFLAG_NEGATIVE)); SetAuraLevel(caster ? caster->getLevel() : sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); UpdateAuraCharges(); SendAuraUpdate(false); @@ -1126,7 +1126,7 @@ void Aura::SendAuraUpdate(bool remove) data << uint8(GetAuraLevel()); data << uint8(GetAuraCharges()); - if(!(auraFlags & AFLAG_NOT_GUID)) + if(!(auraFlags & AFLAG_NOT_CASTER)) { data << uint8(0); // pguid } From 871f2e181c48a711312c5d62f24b76757d391afa Mon Sep 17 00:00:00 2001 From: arrai Date: Sun, 9 Nov 2008 17:32:39 +0100 Subject: [PATCH 087/256] Removed dynamic memory allocations in CriteriaCastSpellRequirements --- src/game/AchievementMgr.cpp | 109 +++++++++++++++++------------------- src/game/AchievementMgr.h | 11 +--- 2 files changed, 55 insertions(+), 65 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index fea132cbe..60366d14e 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -27,60 +27,55 @@ #include "GameEvent.h" #include "World.h" -const CriteriaCastSpellRequirement* AchievementMgr::criteriaCastSpellRequirements[] = +const CriteriaCastSpellRequirement AchievementMgr::criteriaCastSpellRequirements[CRITERIA_CAST_SPELL_REQ_COUNT] = { - new CriteriaCastSpellRequirement(5272, 3057, 0, 0), - new CriteriaCastSpellRequirement(5273, 2784, 0, 0), - new CriteriaCastSpellRequirement(5752, 9099, 0, 0), - new CriteriaCastSpellRequirement(5753, 8403, 0, 0), - - new CriteriaCastSpellRequirement(5772, 0, 0, RACE_GNOME), - new CriteriaCastSpellRequirement(5774, 0, 0, RACE_BLOODELF), - new CriteriaCastSpellRequirement(5775, 0, 0, RACE_DRAENEI), - new CriteriaCastSpellRequirement(5776, 0, 0, RACE_DWARF), - new CriteriaCastSpellRequirement(5777, 0, 0, RACE_HUMAN), - new CriteriaCastSpellRequirement(5778, 0, 0, RACE_NIGHTELF), - new CriteriaCastSpellRequirement(5779, 0, 0, RACE_ORC), - new CriteriaCastSpellRequirement(5780, 0, 0, RACE_TAUREN), - new CriteriaCastSpellRequirement(5781, 0, 0, RACE_TROLL), - new CriteriaCastSpellRequirement(5782, 0, 0, RACE_UNDEAD_PLAYER), - - new CriteriaCastSpellRequirement(6225, 5661, 0, 0), - new CriteriaCastSpellRequirement(6226, 26044, 0, 0), - new CriteriaCastSpellRequirement(6228, 739, 0, 0), - new CriteriaCastSpellRequirement(6229, 927, 0, 0), - new CriteriaCastSpellRequirement(6230, 1444, 0, 0), - new CriteriaCastSpellRequirement(6231, 8140, 0, 0), - new CriteriaCastSpellRequirement(6232, 5489, 0, 0), - new CriteriaCastSpellRequirement(6233,12336, 0, 0), - new CriteriaCastSpellRequirement(6234, 1351, 0, 0), - new CriteriaCastSpellRequirement(6235, 5484, 0, 0), - new CriteriaCastSpellRequirement(6236, 1182, 0, 0), - - new CriteriaCastSpellRequirement(6237, 0, CLASS_DEATH_KNIGHT, RACE_ORC), - new CriteriaCastSpellRequirement(6238, 0, CLASS_WARRIOR, RACE_HUMAN), - new CriteriaCastSpellRequirement(6239, 0, CLASS_SHAMAN, RACE_TAUREN), - new CriteriaCastSpellRequirement(6240, 0, CLASS_DRUID, RACE_NIGHTELF), - new CriteriaCastSpellRequirement(6241, 0, CLASS_ROGUE, RACE_UNDEAD_PLAYER), - new CriteriaCastSpellRequirement(6242, 0, CLASS_HUNTER, RACE_TROLL), - new CriteriaCastSpellRequirement(6243, 0, CLASS_MAGE, RACE_GNOME), - new CriteriaCastSpellRequirement(6244, 0, CLASS_PALADIN, RACE_DWARF), - new CriteriaCastSpellRequirement(6245, 0, CLASS_WARLOCK, RACE_BLOODELF), - new CriteriaCastSpellRequirement(6246, 0, CLASS_PRIEST, RACE_DRAENEI), - - new CriteriaCastSpellRequirement(6312, 0, CLASS_WARLOCK, RACE_GNOME), - new CriteriaCastSpellRequirement(6313, 0, CLASS_DEATH_KNIGHT, RACE_HUMAN), - new CriteriaCastSpellRequirement(6314, 0, CLASS_PRIEST, RACE_NIGHTELF), - new CriteriaCastSpellRequirement(6315, 0, CLASS_SHAMAN, RACE_ORC), - new CriteriaCastSpellRequirement(6316, 0, CLASS_DRUID, RACE_TAUREN), - new CriteriaCastSpellRequirement(6317, 0, CLASS_ROGUE, RACE_TROLL), - new CriteriaCastSpellRequirement(6318, 0, CLASS_WARRIOR, RACE_UNDEAD_PLAYER), - new CriteriaCastSpellRequirement(6319, 0, CLASS_MAGE, RACE_BLOODELF), - new CriteriaCastSpellRequirement(6320, 0, CLASS_PALADIN, RACE_DRAENEI), - new CriteriaCastSpellRequirement(6321, 0, CLASS_HUNTER, RACE_DWARF), - - new CriteriaCastSpellRequirement(6662, 31261, 0, 0), - NULL}; + {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) { @@ -404,13 +399,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) continue; // those requirements couldn't be found in the dbc - const CriteriaCastSpellRequirement *requirement = NULL; - for (uint32 i=0; criteriaCastSpellRequirements[i]; i++) + const CriteriaCastSpellRequirement *requirement = NULL; + for (uint32 i=0; iachievementCriteriaId == achievementCriteria->ID) + if (criteriaCastSpellRequirements[i].achievementCriteriaId == achievementCriteria->ID) { - requirement = criteriaCastSpellRequirements[i]; + requirement = &criteriaCastSpellRequirements[i]; break; } } diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index 9edcf1cbe..98f0fb904 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -23,6 +23,8 @@ #include "Database/DBCStores.h" #include "Database/DatabaseEnv.h" +#define CRITERIA_CAST_SPELL_REQ_COUNT 46 + struct CriteriaProgress { CriteriaProgress(uint32 id, uint32 counter, time_t date = time(NULL)) @@ -38,13 +40,6 @@ struct CriteriaProgress struct CriteriaCastSpellRequirement { - CriteriaCastSpellRequirement(uint32 achievementCriteriaId, uint32 creatureEntry, uint32 playerClass, uint32 playerRace) - { - this->achievementCriteriaId = achievementCriteriaId; - this->creatureEntry = creatureEntry; - this->playerClass = playerClass; - this->playerRace = playerRace; - } uint32 achievementCriteriaId; uint32 creatureEntry; uint8 playerClass; @@ -92,6 +87,6 @@ class AchievementMgr Player* m_player; CriteriaProgressMap m_criteriaProgress; CompletedAchievementMap m_completedAchievements; - static const CriteriaCastSpellRequirement* criteriaCastSpellRequirements[]; + static const CriteriaCastSpellRequirement criteriaCastSpellRequirements[]; }; #endif From 96f2b1d314dc89d16f05e5287bf7be1eb86b6b6c Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 10 Nov 2008 00:56:46 +0300 Subject: [PATCH 088/256] Load SummonProperties.dbc, data not used yet --- src/game/MovementHandler.cpp | 6 +++--- src/game/SharedDefines.h | 16 ++++++++++++++++ src/shared/Database/DBCStores.cpp | 2 ++ src/shared/Database/DBCStores.h | 1 + src/shared/Database/DBCStructure.h | 10 ++++++++++ src/shared/Database/DBCfmt.cpp | 1 + 6 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 0303a7dff..229aff452 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -298,7 +298,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) Player *target = GetPlayer(); //Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored - if (movementInfo.fallTime > 1100 && !target->isDead() && !target->isGameMaster() && + if (movementInfo.fallTime > 1500 && !target->isDead() && !target->isGameMaster() && !target->HasAuraType(SPELL_AURA_HOVER) && !target->HasAuraType(SPELL_AURA_FEATHER_FALL) && !target->HasAuraType(SPELL_AURA_FLY) && !target->IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) ) { @@ -306,10 +306,10 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) int32 safe_fall = target->GetTotalAuraModifier(SPELL_AURA_SAFE_FALL); uint32 fall_time = (movementInfo.fallTime > (safe_fall*10)) ? movementInfo.fallTime - (safe_fall*10) : 0; - if(fall_time > 1100) //Prevent damage if fall time < 1100 + if(fall_time > 1500) //Prevent damage if fall time < 1500 { //Fall Damage calculation - float fallperc = float(fall_time)/1100; + float fallperc = float(fall_time)/1500; uint32 damage = (uint32)(((fallperc*fallperc -1) / 9 * target->GetMaxHealth())*sWorld.getRate(RATE_DAMAGE_FALL)); float height = movementInfo.z; diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 24042c31a..ca6c4b217 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -2061,6 +2061,22 @@ enum SummonType SUMMON_TYPE_POSESSED2 = 428 }; +enum SummonType2 +{ + SUMMON_TYPE2_UNKNOWN = 0, + SUMMON_TYPE2_SUMMON = 1, + SUMMON_TYPE2_GUARDIAN = 2, + SUMMON_TYPE2_DEMON = 3, + SUMMON_TYPE2_TOTEM = 4, + SUMMON_TYPE2_CRITTER = 5, + SUMMON_TYPE2_GHOUL = 6, + SUMMON_TYPE2_BOMB = 7, + SUMMON_TYPE2_PHASING = 8, + SUMMON_TYPE2_SIEGE_VEH = 9, + SUMMON_TYPE2_DRAKE_VEH = 10, + SUMMON_TYPE2_LIGHTWELL = 11 +}; + enum ResponseCodes { RESPONSE_SUCCESS = 0x00, diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp index 60f9e21c4..f501c1f80 100644 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -109,6 +109,7 @@ DBCStorage sSpellRangeStore(SpellRangefmt); DBCStorage sSpellRuneCostStore(SpellRuneCostfmt); DBCStorage sSpellShapeshiftStore(SpellShapeshiftfmt); DBCStorage sStableSlotPricesStore(StableSlotPricesfmt); +DBCStorage sSummonPropertiesStore(SummonPropertiesfmt); DBCStorage sTalentStore(TalentEntryfmt); TalentSpellPosMap sTalentSpellPosMap; DBCStorage sTalentTabStore(TalentTabEntryfmt); @@ -318,6 +319,7 @@ void LoadDBCStores(std::string dataPath) 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 diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h index 0e6664394..af8baa5eb 100644 --- a/src/shared/Database/DBCStores.h +++ b/src/shared/Database/DBCStores.h @@ -191,6 +191,7 @@ extern DBCStorage sSpellRuneCostStore; extern DBCStorage sSpellShapeshiftStore; extern DBCStorage sSpellStore; extern DBCStorage sStableSlotPricesStore; +extern DBCStorage sSummonPropertiesStore; extern DBCStorage sTalentStore; extern DBCStorage sTalentTabStore; extern DBCStorage sTaxiNodesStore; diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 7937efdac..016b5570f 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -1234,6 +1234,16 @@ struct StableSlotPricesEntry uint32 Price; }; +struct SummonPropertiesEntry +{ + uint32 Id; + uint32 Unk1; + uint32 Unk2; + uint32 Type; + uint32 Slot; + uint32 Flags; +}; + struct TalentEntry { uint32 TalentID; // 0 diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index aa2564ab8..b67c18bbe 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -77,6 +77,7 @@ const char SpellRangefmt[]="nfxfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char SpellRuneCostfmt[]="niiii"; const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxx"; const char StableSlotPricesfmt[] = "ni"; +const char SummonPropertiesfmt[] = "niiiii"; const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx"; const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiiix"; const char TaxiNodesEntryfmt[]="nifffxxxxxxxxxxxxxxxxxii"; From 204b61c2200466311cc665e475dc88385a971480 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Tue, 11 Nov 2008 00:05:00 +0300 Subject: [PATCH 089/256] Added empty vehicle class, vehicle*.dbc struct's --- src/game/Makefile.am | 2 + src/game/ObjectAccessor.cpp | 5 +- src/game/ObjectAccessor.h | 3 +- src/game/ObjectDefines.h | 2 +- src/game/ObjectMgr.cpp | 11 ++++ src/game/ObjectMgr.h | 1 + src/game/SharedDefines.h | 16 ----- src/game/Unit.cpp | 2 +- src/game/Vehicle.cpp | 78 ++++++++++++++++++++++ src/game/Vehicle.h | 52 +++++++++++++++ src/game/World.cpp | 6 ++ src/shared/Database/DBCEnums.h | 47 +++++++++++++ src/shared/Database/DBCStores.cpp | 4 +- src/shared/Database/DBCStores.h | 2 +- src/shared/Database/DBCStructure.h | 102 ++++++++++++++++++++++++++--- src/shared/Database/DBCfmt.cpp | 2 +- win/VC71/game.vcproj | 6 ++ win/VC80/game.vcproj | 8 +++ win/VC90/game.vcproj | 8 +++ 19 files changed, 323 insertions(+), 34 deletions(-) create mode 100644 src/game/Vehicle.cpp create mode 100644 src/game/Vehicle.h diff --git a/src/game/Makefile.am b/src/game/Makefile.am index 823681525..aac9b125e 100644 --- a/src/game/Makefile.am +++ b/src/game/Makefile.am @@ -249,6 +249,8 @@ libmangosgame_a_SOURCES = \ UpdateData.h \ UpdateFields.h \ UpdateMask.h \ + Vehicle.cpp \ + Vehicle.h \ VoiceChatHandler.cpp \ WaypointManager.cpp \ WaypointManager.h \ diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 586f84a82..febb0148e 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -45,7 +45,6 @@ INSTANTIATE_CLASS_MUTEX(ObjectAccessor, ZThread::FastMutex); namespace MaNGOS { - struct MANGOS_DLL_DECL BuildUpdateForPlayer { Player &i_player; @@ -631,10 +630,11 @@ void ObjectAccessor::UpdateVisibilityForPlayer( Player* player ) template UNORDERED_MAP< uint64, T* > HashMapHolder::m_objectMap; template ZThread::FastMutex HashMapHolder::i_lock; -/// Global defintions for the hashmap storage +/// Global definitions for the hashmap storage template class HashMapHolder; template class HashMapHolder; +template class HashMapHolder; template class HashMapHolder; template class HashMapHolder; template class HashMapHolder; @@ -642,6 +642,7 @@ template class HashMapHolder; template Player* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Player* /*fake*/); template Pet* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Pet* /*fake*/); +template Vehicle* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Vehicle* /*fake*/); template Creature* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Creature* /*fake*/); template Corpse* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, Corpse* /*fake*/); template GameObject* ObjectAccessor::GetObjectInWorld(uint32 mapid, float x, float y, uint64 guid, GameObject* /*fake*/); diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index ccb5b8af8..c6f9815e7 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -31,6 +31,7 @@ #include "GridDefines.h" #include "Object.h" #include "Player.h" +#include "Vehicle.h" #include @@ -72,7 +73,7 @@ class HashMapHolder static LockType* GetLock() { return &i_lock; } private: - //Non instanciable only static + //Non instanceable only static HashMapHolder() {} static LockType i_lock; diff --git a/src/game/ObjectDefines.h b/src/game/ObjectDefines.h index 32a64d291..44da3a89a 100644 --- a/src/game/ObjectDefines.h +++ b/src/game/ObjectDefines.h @@ -39,7 +39,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 F540 + 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) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 548037705..c5cc32fe2 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -110,6 +110,7 @@ ObjectMgr::ObjectMgr() m_hiCharGuid = 1; m_hiCreatureGuid = 1; m_hiPetGuid = 1; + m_hiVehicleGuid = 1; m_hiItemGuid = 1; m_hiGoGuid = 1; m_hiDoGuid = 1; @@ -5102,6 +5103,8 @@ void ObjectMgr::SetHighestGuids() // pet guids are not saved to DB, set to 0 (pet guid != pet id) m_hiPetGuid = 0; + // same for vehicles + m_hiVehicleGuid = 0; result = CharacterDatabase.Query( "SELECT MAX(guid) FROM item_instance" ); if( result ) @@ -5279,6 +5282,14 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) sWorld.m_stopEvent = true; } return m_hiPetGuid; + case HIGHGUID_VEHICLE: + ++m_hiVehicleGuid; + if(m_hiVehicleGuid>=0x00FFFFFF) + { + sLog.outError("Vehicle guid overflow!! Can't continue, shutting down server. "); + sWorld.m_stopEvent = true; + } + return m_hiVehicleGuid; case HIGHGUID_PLAYER: ++m_hiCharGuid; if(m_hiCharGuid>=0xFFFFFFFF) diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 6f1fc3fc4..769fbfc7b 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -772,6 +772,7 @@ class ObjectMgr uint32 m_hiCharGuid; uint32 m_hiCreatureGuid; uint32 m_hiPetGuid; + uint32 m_hiVehicleGuid; uint32 m_hiItemGuid; uint32 m_hiGoGuid; uint32 m_hiDoGuid; diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 5e17538c4..14072c790 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -2063,22 +2063,6 @@ enum SummonType SUMMON_TYPE_POSESSED2 = 428 }; -enum SummonType2 -{ - SUMMON_TYPE2_UNKNOWN = 0, - SUMMON_TYPE2_SUMMON = 1, - SUMMON_TYPE2_GUARDIAN = 2, - SUMMON_TYPE2_DEMON = 3, - SUMMON_TYPE2_TOTEM = 4, - SUMMON_TYPE2_CRITTER = 5, - SUMMON_TYPE2_GHOUL = 6, - SUMMON_TYPE2_BOMB = 7, - SUMMON_TYPE2_PHASING = 8, - SUMMON_TYPE2_SIEGE_VEH = 9, - SUMMON_TYPE2_DRAKE_VEH = 10, - SUMMON_TYPE2_LIGHTWELL = 11 -}; - enum ResponseCodes { RESPONSE_SUCCESS = 0x00, diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 355e122ed..2aa7b27fb 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -146,7 +146,7 @@ Unit::Unit() m_objectType |= TYPEMASK_UNIT; m_objectTypeId = TYPEID_UNIT; // 2.3.2 - 0x70 - m_updateFlag = (UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION); + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION); m_attackTimer[BASE_ATTACK] = 0; m_attackTimer[OFF_ATTACK] = 0; diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp new file mode 100644 index 000000000..acfd00f58 --- /dev/null +++ b/src/game/Vehicle.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This 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_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) +{ + SetMapId(map->GetId()); + SetInstanceId(map->GetInstanceId()); + + Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE); + + if(!InitEntry(Entry)) + return false; + + return true; +} diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h new file mode 100644 index 000000000..75ff3375c --- /dev/null +++ b/src/game/Vehicle.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2008 MaNGOS + * + * This 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); + + void setDeathState(DeathState s); // overwrite virtual Creature::setDeathState and Unit::setDeathState + void Update(uint32 diff); // overwrite virtual Creature::Update and Unit::Update + + protected: + + 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/World.cpp b/src/game/World.cpp index b08e55180..dda2b29ca 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1513,6 +1513,9 @@ void World::ScriptsProcess() case HIGHGUID_PET: source = HashMapHolder::Find(step.sourceGUID); break; + case HIGHGUID_VEHICLE: + source = HashMapHolder::Find(step.sourceGUID); + break; case HIGHGUID_PLAYER: source = HashMapHolder::Find(step.sourceGUID); break; @@ -1540,6 +1543,9 @@ void World::ScriptsProcess() case HIGHGUID_PET: target = HashMapHolder::Find(step.targetGUID); break; + case HIGHGUID_VEHICLE: + target = HashMapHolder::Find(step.targetGUID); + break; case HIGHGUID_PLAYER: // empty GUID case also target = HashMapHolder::Find(step.targetGUID); break; diff --git a/src/shared/Database/DBCEnums.h b/src/shared/Database/DBCEnums.h index ebe0e6ae1..e83058fdd 100644 --- a/src/shared/Database/DBCEnums.h +++ b/src/shared/Database/DBCEnums.h @@ -248,4 +248,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 f501c1f80..f3c15d518 100644 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -109,7 +109,7 @@ DBCStorage sSpellRangeStore(SpellRangefmt); DBCStorage sSpellRuneCostStore(SpellRuneCostfmt); DBCStorage sSpellShapeshiftStore(SpellShapeshiftfmt); DBCStorage sStableSlotPricesStore(StableSlotPricesfmt); -DBCStorage sSummonPropertiesStore(SummonPropertiesfmt); +//DBCStorage sSummonPropertiesStore(SummonPropertiesfmt); DBCStorage sTalentStore(TalentEntryfmt); TalentSpellPosMap sTalentSpellPosMap; DBCStorage sTalentTabStore(TalentTabEntryfmt); @@ -319,7 +319,7 @@ void LoadDBCStores(std::string dataPath) 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,sSummonPropertiesStore, dbcPath,"SummonProperties.dbc"); LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentStore, dbcPath,"Talent.dbc"); // create talent spells set diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h index af8baa5eb..b5c268258 100644 --- a/src/shared/Database/DBCStores.h +++ b/src/shared/Database/DBCStores.h @@ -191,7 +191,7 @@ extern DBCStorage sSpellRuneCostStore; extern DBCStorage sSpellShapeshiftStore; extern DBCStorage sSpellStore; extern DBCStorage sStableSlotPricesStore; -extern DBCStorage sSummonPropertiesStore; +//extern DBCStorage sSummonPropertiesStore; extern DBCStorage sTalentStore; extern DBCStorage sTalentTabStore; extern DBCStorage sTaxiNodesStore; diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 016b5570f..b5c7105ec 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -1100,7 +1100,7 @@ struct SpellEntry uint32 StartRecoveryTime; // 209 m_startRecoveryTime uint32 MaxTargetLevel; // 210 m_maxTargetLevel uint32 SpellFamilyName; // 211 m_spellClassSet - uint64 SpellFamilyFlags; // 212-213 m_spellClassMask + uint64 SpellFamilyFlags; // 212-213 m_spellClassMask NOTE: size is 12 bytes!!! uint32 SpellFamilyFlags2; // 214 addition to m_spellClassMask uint32 MaxAffectedTargets; // 215 m_maxTargets uint32 DmgClass; // 216 m_defenseType @@ -1234,15 +1234,15 @@ struct StableSlotPricesEntry uint32 Price; }; -struct SummonPropertiesEntry +/*struct SummonPropertiesEntry { - uint32 Id; - uint32 Unk1; - uint32 Unk2; - uint32 Type; - uint32 Slot; - uint32 Flags; -}; + 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 { @@ -1320,6 +1320,90 @@ 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 diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index b67c18bbe..4ec736006 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -77,7 +77,7 @@ const char SpellRangefmt[]="nfxfxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char SpellRuneCostfmt[]="niiii"; const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxx"; const char StableSlotPricesfmt[] = "ni"; -const char SummonPropertiesfmt[] = "niiiii"; +//const char SummonPropertiesfmt[] = "niiiii"; const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxxxx"; const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiiix"; const char TaxiNodesEntryfmt[]="nifffxxxxxxxxxxxxxxxxxii"; diff --git a/win/VC71/game.vcproj b/win/VC71/game.vcproj index 4edea3afb..cb5d435ca 100644 --- a/win/VC71/game.vcproj +++ b/win/VC71/game.vcproj @@ -758,6 +758,12 @@ + + + + diff --git a/win/VC80/game.vcproj b/win/VC80/game.vcproj index 0cf8da463..652810ad2 100644 --- a/win/VC80/game.vcproj +++ b/win/VC80/game.vcproj @@ -1182,6 +1182,14 @@ RelativePath="..\..\src\game\UpdateMask.h" > + + + + diff --git a/win/VC90/game.vcproj b/win/VC90/game.vcproj index 97d4d01d5..f2b676fd5 100644 --- a/win/VC90/game.vcproj +++ b/win/VC90/game.vcproj @@ -1184,6 +1184,14 @@ RelativePath="..\..\src\game\UpdateMask.h" > + + + + From 871d5f8c99b3dd19ae0ef9fdbb4aeb963b68838d Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 12 Nov 2008 00:49:19 +0300 Subject: [PATCH 090/256] Small progress with vehicles --- src/game/Chat.cpp | 1 + src/game/Chat.h | 1 + src/game/Creature.cpp | 2 +- src/game/Creature.h | 2 + src/game/Level2.cpp | 2 +- src/game/Map.cpp | 4 +- src/game/MiscHandler.cpp | 11 +++--- src/game/MovementHandler.cpp | 2 +- src/game/Object.cpp | 8 +++- src/game/ObjectAccessor.cpp | 9 +++++ src/game/ObjectAccessor.h | 1 + src/game/ObjectGridLoader.cpp | 4 +- src/game/Player.cpp | 69 +++++++++++++++++++++++++++++++++++ src/game/Player.h | 8 +++- src/game/Unit.cpp | 2 +- src/game/Vehicle.cpp | 21 +++++++++-- src/game/Vehicle.h | 6 ++- src/game/debugcmds.cpp | 43 ++++++++++++++++++++++ 18 files changed, 175 insertions(+), 21 deletions(-) diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index d77838cfe..89051e9f8 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -157,6 +157,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 }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 86f310ee5..1b7db35d6 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -427,6 +427,7 @@ class ChatHandler bool HandleSaveAllCommand(const char* args); bool HandleGetItemState(const char * args); bool HandleGetLootRecipient(const char * args); + bool HandleSpawnVehicle(const char * args); Player* getSelectedPlayer(); Creature* getSelectedCreature(); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index d03b1d416..1caca9270 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1696,7 +1696,7 @@ void Creature::CallAssistence() void Creature::SaveRespawnTime() { - if(isPet() || !m_DBTableGuid) + if(isPet() || isVehicle() || !m_DBTableGuid) return; if(m_respawnTime > time(NULL)) // dead (no corpse) diff --git a/src/game/Creature.h b/src/game/Creature.h index 4f5dd1d51..a95a3998b 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -410,6 +410,7 @@ class MANGOS_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; } @@ -618,6 +619,7 @@ class MANGOS_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 void RegenerateMana(); void RegenerateHealth(); diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index c9b3b351d..b86d648f8 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -949,7 +949,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); diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 029c59719..061fb0d31 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -253,7 +253,7 @@ template<> void Map::AddToGrid(Creature* obj, NGridType *grid, Cell const& cell) { // add to world object registry in grid - if(obj->isPet()) + if(obj->isPet() || obj->isVehicle()) { (*grid)(cell.CellX(), cell.CellY()).AddWorldObject(obj, obj->GetGUID()); obj->SetCurrentCell(cell); @@ -297,7 +297,7 @@ template<> void Map::RemoveFromGrid(Creature* obj, NGridType *grid, Cell const& cell) { // remove from world object registry in grid - if(obj->isPet()) + if(obj->isPet() || obj->isVehicle()) { (*grid)(cell.CellX(), cell.CellY()).RemoveWorldObject(obj, obj->GetGUID()); } diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index b5d970bf4..eb0ed5c2f 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1661,15 +1661,16 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data ) uint64 guid; recv_data >> guid; - Unit *vehicle = ObjectAccessor::GetUnit(*_player, guid); + Vehicle *vehicle = ObjectAccessor::GetVehicle(guid); if(!vehicle) return; - _player->SetClientControl(vehicle, 1); - _player->CastSpell(_player, 43768, true); - _player->SetUInt64Value(UNIT_FIELD_CHARM, guid); - _player->SetUInt64Value(PLAYER_FARSIGHT, guid); + //_player->SetClientControl(vehicle, 1); + //_player->CastSpell(_player, 43768, true); + //_player->SetUInt64Value(UNIT_FIELD_CHARM, guid); + //_player->SetUInt64Value(PLAYER_FARSIGHT, guid); + _player->EnterVehicle(vehicle); } void WorldSession::HandleInspectAchievements( WorldPacket & recv_data ) diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 229aff452..cd7e4a81d 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -201,7 +201,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) recv_data >> movementInfo.t_z; recv_data >> movementInfo.t_o; recv_data >> movementInfo.t_time; - recv_data >> movementInfo.t_unk; + recv_data >> movementInfo.t_seat; } if((MovementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) || (movementInfo.unk1 & 0x20)) diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 81a29276b..42b5833ba 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -258,6 +258,10 @@ void Object::DestroyForPlayer(Player *target) 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 @@ -331,7 +335,7 @@ 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 << (uint8)((Player*)this)->GetTransUnk(); + *data << (int8)((Player*)this)->GetTransSeat(); } //MaNGOS currently not have support for other than player on transport } @@ -544,7 +548,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2) // 0x80 if(flags & UPDATEFLAG_VEHICLE) // unused for now { - *data << uint32(0); // vehicle id + *data << uint32(((Vehicle*)this)->GetVehicleId()); // vehicle id *data << float(0); // facing adjustment } } diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index febb0148e..61c92db3d 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -132,6 +132,9 @@ ObjectAccessor::GetCreatureOrPet(WorldObject const &u, uint64 guid) if(Creature *unit = GetPet(guid)) return unit; + if(Creature *unit = GetVehicle(guid)) + return unit; + return GetCreature(u, guid); } @@ -367,6 +370,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) { diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index c6f9815e7..fbf60baaf 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -149,6 +149,7 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::SingletongetSource(); - 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/Player.cpp b/src/game/Player.cpp index 6c7c9997a..61db3b8b2 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18596,3 +18596,72 @@ void Player::InitGlyphsForLevel() SetUInt32Value(PLAYER_GLYPHS_ENABLED, value); } + +void Player::EnterVehicle(Vehicle *vehicle) +{ + vehicle->SetCharmerGUID(GetGUID()); + vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + vehicle->setFaction(getFaction()); + + SetCharm(vehicle); + SetUInt64Value(PLAYER_FARSIGHT, vehicle->GetGUID()); + + SetClientControl(vehicle, 1); + + WorldPacket data(SMSG_UNKNOWN_1181, 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 + data << vehicle->GetGUID(); // transport guid + data << float(0); // transport offsetX + data << float(0); // transport offsetY + data << float(1); // 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); +} + +void Player::ExitVehicle(Vehicle *vehicle) +{ + vehicle->SetCharmerGUID(0); + vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H); + + SetCharm(NULL); + SetUInt64Value(PLAYER_FARSIGHT, 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); + + // only for flyable vehicles? + CastSpell(this, 45472, true); // Parachute +} diff --git a/src/game/Player.h b/src/game/Player.h index e640524c3..d38bb079d 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -47,6 +47,7 @@ class Transport; class UpdateMask; class PlayerSocial; class AchievementMgr; +class Vehicle; typedef std::deque PlayerMails; @@ -736,7 +737,7 @@ struct MovementInfo uint64 t_guid; float t_x, t_y, t_z, t_o; uint32 t_time; - uint8 t_unk; + int8 t_seat; // swimming and unknown float s_pitch; // last fall time @@ -1950,6 +1951,9 @@ class MANGOS_DLL_SPEC Player : public Unit void SetClientControl(Unit* target, uint8 allowMove); + void EnterVehicle(Vehicle *vehicle); + void ExitVehicle(Vehicle *vehicle); + // Transports Transport * GetTransport() const { return m_transport; } void SetTransport(Transport * t) { m_transport = t; } @@ -1959,7 +1963,7 @@ class MANGOS_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; } - uint8 GetTransUnk() const { return m_movementInfo.t_unk; } + int8 GetTransSeat() const { return m_movementInfo.t_seat; } uint32 GetSaveTimer() const { return m_nextSave; } void SetSaveTimer(uint32 timer) { m_nextSave = timer; } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 2aa7b27fb..da1894338 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9061,7 +9061,7 @@ bool Unit::CanHaveThreatList() const return false; // pets and totems can not have threat list - if( ((Creature*)this)->isPet() || ((Creature*)this)->isTotem() ) + if( ((Creature*)this)->isPet() || ((Creature*)this)->isTotem() || ((Creature*)this)->isVehicle() ) return false; return true; diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp index acfd00f58..f61e14cbb 100644 --- a/src/game/Vehicle.cpp +++ b/src/game/Vehicle.cpp @@ -28,8 +28,9 @@ #include "Unit.h" #include "Util.h" -Vehicle::Vehicle() : Creature() +Vehicle::Vehicle() : Creature(), m_vehicleId(0) { + m_isVehicle = true; m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_LIVING | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_VEHICLE); } @@ -64,15 +65,29 @@ void Vehicle::Update(uint32 diff) Creature::Update(diff); } -bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry) +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)) + if(!InitEntry(Entry, team)) return false; + m_defaultMovementType = IDLE_MOTION_TYPE; + + AIM_Initialize(); + + SetVehicleId(vehicleId); + + SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + + CreatureInfo const *ci = GetCreatureInfo(); + setFaction(team == ALLIANCE ? ci->faction_A : ci->faction_H); + SetMaxHealth(ci->maxhealth); + SelectLevel(ci); + SetHealth(GetMaxHealth()); + return true; } diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h index 75ff3375c..0479d96f8 100644 --- a/src/game/Vehicle.h +++ b/src/game/Vehicle.h @@ -32,12 +32,16 @@ class Vehicle : public Creature void AddToWorld(); void RemoveFromWorld(); - bool Create (uint32 guidlow, Map *map, uint32 Entry); + 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; } + protected: + uint32 m_vehicleId; private: void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index b81ad0a63..fe6b88760 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -31,6 +31,7 @@ #include "Language.h" #include "MapManager.h" #include +#include "ObjectMgr.h" bool ChatHandler::HandleDebugInArcCommand(const char* /*args*/) { @@ -518,3 +519,45 @@ bool ChatHandler::HandleGetItemState(const char* args) 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); + + // TODO: check entry, id... + + 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; +} From 14d312ad226a37d0dba88a4bbb425fdd2e714489 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 12 Nov 2008 23:20:59 +0300 Subject: [PATCH 091/256] More work on vehicles --- src/game/Creature.cpp | 2 +- src/game/MiscHandler.cpp | 19 ++++++++++++++----- src/game/Opcodes.cpp | 2 +- src/game/Player.cpp | 27 +++++++++++++++++++++++++-- src/game/Unit.h | 7 ++++--- src/game/Vehicle.cpp | 4 ++++ src/game/WorldSession.h | 3 ++- 7 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 1caca9270..d03b1d416 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1696,7 +1696,7 @@ void Creature::CallAssistence() void Creature::SaveRespawnTime() { - if(isPet() || isVehicle() || !m_DBTableGuid) + if(isPet() || !m_DBTableGuid) return; if(m_respawnTime > time(NULL)) // dead (no corpse) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index eb0ed5c2f..e585de1ee 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1666,13 +1666,23 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data ) if(!vehicle) return; - //_player->SetClientControl(vehicle, 1); - //_player->CastSpell(_player, 43768, true); - //_player->SetUInt64Value(UNIT_FIELD_CHARM, guid); - //_player->SetUInt64Value(PLAYER_FARSIGHT, guid); _player->EnterVehicle(vehicle); } +void WorldSession::HandleDismissControlledVehicle( WorldPacket & recv_data ) +{ + //CHECK_PACKET_SIZE(recv_data, 8); + recv_data.hexlike(); // standard movement packet + + // using charm guid, because we don't have vehicle guid... + Vehicle *vehicle = ObjectAccessor::GetVehicle(_player->GetCharmGUID()); + + if(!vehicle) + return; + + _player->ExitVehicle(vehicle); +} + void WorldSession::HandleInspectAchievements( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 1); @@ -1686,4 +1696,3 @@ void WorldSession::HandleInspectAchievements( WorldPacket & recv_data ) player->GetAchievementMgr().SendRespondInspectAchievements(_player); } - diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 7a2f65cff..644c4ecdc 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -1159,7 +1159,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*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_NEVER, &WorldSession::Handle_NULL }, + /*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 }, diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 61db3b8b2..76dd63e83 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18601,9 +18601,13 @@ void Player::EnterVehicle(Vehicle *vehicle) { vehicle->SetCharmerGUID(GetGUID()); vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + //vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); vehicle->setFaction(getFaction()); + //vehicle->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); + //vehicle->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 2147483647); + //vehicle->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); + //vehicle->SetUInt32Value(UNIT_FIELD_BYTES_1, 0x02000000); SetCharm(vehicle); SetUInt64Value(PLAYER_FARSIGHT, vehicle->GetGUID()); @@ -18634,15 +18638,29 @@ void Player::EnterVehicle(Vehicle *vehicle) // 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_PVP_ATTACKABLE); + //vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H); + //vehicle->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); SetCharm(NULL); SetUInt64Value(PLAYER_FARSIGHT, 0); @@ -18662,6 +18680,11 @@ void Player::ExitVehicle(Vehicle *vehicle) 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 } diff --git a/src/game/Unit.h b/src/game/Unit.h index c766bea1e..5dd7c8e96 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -490,9 +490,10 @@ enum UnitFlags // 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_COMPREHEND_LANG = 0x00000008, + UNIT_FLAG2_FORCE_MOVE = 0x00000040, + UNIT_FLAG2_UNKNOWN1 = 0x00000800 }; /// Non Player Character flags diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp index f61e14cbb..0955d80c3 100644 --- a/src/game/Vehicle.cpp +++ b/src/game/Vehicle.cpp @@ -82,6 +82,10 @@ bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, u SetVehicleId(vehicleId); SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + SetUInt32Value(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_UNKNOWN1); + SetUInt32Value(UNIT_FIELD_BYTES_1, 0x02000001); + SetUInt32Value(UNIT_FIELD_BYTES_2, 0x00000001); + SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 3.0f); CreatureInfo const *ci = GetCreatureInfo(); setFaction(team == ALLIANCE ? ci->faction_A : ci->faction_H); diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 1b2269e2b..df306a616 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -551,7 +551,8 @@ class MANGOS_DLL_SPEC WorldSession void HandlePetUnlearnOpcode( WorldPacket& recvPacket ); void HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ); void HandlePetCastSpellOpcode( WorldPacket& recvPacket ); - void HandlePetLearnTalent( WorldPacket& recvPacket );; + void HandlePetLearnTalent( WorldPacket& recvPacket ); + void HandleDismissControlledVehicle( WorldPacket& recvPacket ); void HandleSetActionBar(WorldPacket& recv_data); From efdb8e01dd857df1c3a0d784d60a60d2a1ebb66e Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 15 Nov 2008 22:04:00 +0300 Subject: [PATCH 092/256] Removed direct use of some updatefields --- src/game/MiscHandler.cpp | 2 +- src/game/MovementHandler.cpp | 71 ++++++++++++++++++++++++++++++++---- src/game/Opcodes.cpp | 2 +- src/game/Pet.cpp | 4 +- src/game/Player.cpp | 20 ++++++---- src/game/Player.h | 4 ++ src/game/Spell.cpp | 2 + src/game/SpellAuras.cpp | 18 ++++----- src/game/SpellEffects.cpp | 19 +++++----- src/game/Totem.cpp | 7 ++-- src/game/Unit.cpp | 15 +++++--- src/game/Unit.h | 8 +++- src/game/WorldSession.h | 1 + 13 files changed, 122 insertions(+), 51 deletions(-) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index c27df41d4..7ed3b57cb 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1467,7 +1467,7 @@ void WorldSession::HandleFarSightOpcode( WorldPacket & recv_data ) sLog.outDebug("Removed FarSight from player %u", _player->GetGUIDLow()); break; case 1: - sLog.outDebug("Added FarSight " I64FMTD " to player %u", _player->GetUInt64Value(PLAYER_FARSIGHT), _player->GetGUIDLow()); + sLog.outDebug("Added FarSight " I64FMT " to player %u", _player->GetFarSight(), _player->GetGUIDLow()); break; } } diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index cd7e4a81d..13b987610 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -187,9 +187,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) recv_data >> movementInfo.z; recv_data >> movementInfo.o; - //Save movement flags - _player->SetUnitMovementFlags(MovementFlags); - if(MovementFlags & MOVEMENTFLAG_ONTRANSPORT) { // recheck @@ -360,14 +357,34 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) /*----------------------*/ /* process position-change */ + Unit *mover = _player->m_mover; recv_data.put(6, getMSTime()); // offset flags(4) + unk(2) - WorldPacket data(recv_data.GetOpcode(), (GetPlayer()->GetPackGUID().size()+recv_data.size())); - data.append(GetPlayer()->GetPackGUID()); + 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(!_player->GetCharmGUID()) + { + _player->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + _player->m_movementInfo = movementInfo; + _player->SetUnitMovementFlags(MovementFlags); + } + else + { + if(mover->GetTypeId() != TYPEID_PLAYER) + { + mover->Relocate(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + mover->SetUnitMovementFlags(MovementFlags); + } + else + { + ((Player*)mover)->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + ((Player*)mover)->m_movementInfo = movementInfo; + ((Player*)mover)->SetUnitMovementFlags(MovementFlags); + } + } + if (GetPlayer()->m_fallMovementInfo.fallTime >= movementInfo.fallTime || GetPlayer()->m_fallMovementInfo.z <=movementInfo.z) GetPlayer()->m_fallMovementInfo = movementInfo; @@ -520,17 +537,55 @@ 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; + if(_player->GetGUID() == guid) + { + if(_player->GetCharmGUID() == 0) + _player->m_mover = _player; + } + else + { + if(_player->GetCharmGUID() == guid) + { + if(IS_PLAYER_GUID(guid)) + { + if(Player *plr = objmgr.GetPlayer(guid)) + _player->m_mover = plr; + } + else if(IS_CREATURE_OR_PET_GUID(guid)) + { + if(Creature *creature = ObjectAccessor::GetCreatureOrPet(*_player, guid)) + _player->m_mover = creature; + } + else if(IS_VEHICLE_GUID(guid)) + { + if(Vehicle *vehicle = ObjectAccessor::GetVehicle(guid)) + _player->m_mover = vehicle; + } + else + { + sLog.outError("Unknown guid " I64FMT "in HandleSetActiveMoverOpcode", guid); + } + } + } + WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement data << uint32(0x00000000); // on blizz it increments periodically SendPacket(&data); } +void WorldSession::HandleMoveNotActiveMoverOpcode(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER"); + recv_data.hexlike(); // normal movement packet +} + void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/) { //sLog.outDebug("WORLD: Recvd CMSG_MOUNTSPECIAL_ANIM"); diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 644c4ecdc..4e6825606 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -747,7 +747,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*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_NEVER, &WorldSession::Handle_NULL }, + /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleMoveNotActiveMoverOpcode }, /*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 }, diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 466405175..4838ac098 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -189,7 +189,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu 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(); @@ -224,7 +224,7 @@ bool Pet::LoadPetFromDB( Unit* owner, uint32 petentry, uint32 petnumber, bool cu 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())); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index d6a889110..606d1e7bf 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -423,6 +423,8 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) //Default movement to run mode m_unit_movement_flags = 0; + m_mover = NULL; + m_miniPet = 0; m_bgAfkReportedTimer = 0; m_contestedPvPTimer = 0; @@ -13902,14 +13904,14 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) SetUInt32Value(UNIT_CHANNEL_SPELL,0); // clear charm/summon related fields - SetUInt64Value(UNIT_FIELD_CHARM,0); - SetUInt64Value(UNIT_FIELD_SUMMON,0); - SetUInt64Value(UNIT_FIELD_CHARMEDBY,0); - SetUInt64Value(UNIT_FIELD_SUMMONEDBY,0); - SetUInt64Value(UNIT_FIELD_CREATEDBY,0); + SetCharm(NULL); + SetPet(NULL); + SetCharmerGUID(NULL); + SetOwnerGUID(NULL); + SetCreatorGUID(NULL); // reset some aura modifiers before aura apply - SetUInt64Value(PLAYER_FARSIGHT, 0); + SetFarSight(NULL); SetUInt32Value(PLAYER_TRACK_CREATURES, 0 ); SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 ); @@ -17522,6 +17524,8 @@ void Player::SendInitialPacketsBeforeAddToMap() // 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() @@ -18638,7 +18642,7 @@ void Player::EnterVehicle(Vehicle *vehicle) //vehicle->SetUInt32Value(UNIT_FIELD_BYTES_1, 0x02000000); SetCharm(vehicle); - SetUInt64Value(PLAYER_FARSIGHT, vehicle->GetGUID()); + SetFarSight(vehicle->GetGUID()); SetClientControl(vehicle, 1); @@ -18691,7 +18695,7 @@ void Player::ExitVehicle(Vehicle *vehicle) //vehicle->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); SetCharm(NULL); - SetUInt64Value(PLAYER_FARSIGHT, 0); + SetFarSight(NULL); SetClientControl(vehicle, 0); diff --git a/src/game/Player.h b/src/game/Player.h index d38bb079d..38f48c1e9 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1941,6 +1941,7 @@ class MANGOS_DLL_SPEC Player : public Unit /*********************************************************/ MovementInfo m_movementInfo; MovementInfo m_fallMovementInfo; + Unit *m_mover; bool isMoving() const { return HasUnitMovementFlag(movementFlagsMask); } bool isMovingOrTurning() const { return HasUnitMovementFlag(movementOrTurningFlagsMask); } @@ -1954,6 +1955,9 @@ class MANGOS_DLL_SPEC Player : public Unit void EnterVehicle(Vehicle *vehicle); void ExitVehicle(Vehicle *vehicle); + uint64 GetFarSight() const { return GetUInt64Value(PLAYER_FARSIGHT); } + void SetFarSight(uint64 guid) { SetUInt64Value(PLAYER_FARSIGHT, guid); } + // Transports Transport * GetTransport() const { return m_transport; } void SetTransport(Transport * t) { m_transport = t; } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 6fb3b292e..0854606bd 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -270,6 +270,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi m_triggeringContainer = triggeringContainer; m_referencedFromCurrentSpell = false; m_executedCurrently = false; + m_delayStart = 0; m_delayAtDamageCount = 0; m_applyMultiplierMask = 0; @@ -336,6 +337,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi gameObjTarget = NULL; focusObject = NULL; m_cast_count = 0; + m_glyphIndex = 0; m_triggeredByAuraSpell = NULL; //Auto Shot & Shoot diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index e1dd97ac0..e775150e1 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2000,7 +2000,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) ( GetSpellProto()->EffectApplyAuraName[0]==1 || GetSpellProto()->EffectApplyAuraName[0]==128 ) ) ) { // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425 - m_target->SetUInt64Value(PLAYER_FARSIGHT, 0); + ((Player*)m_target)->SetFarSight(NULL); WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0); ((Player*)m_target)->GetSession()->SendPacket(&data); return; @@ -2858,7 +2858,7 @@ void Aura::HandleBindSight(bool apply, bool Real) if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; - caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_target->GetGUID() : 0); + ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); } void Aura::HandleFarSight(bool apply, bool Real) @@ -2867,7 +2867,7 @@ void Aura::HandleFarSight(bool apply, bool Real) if(!caster || caster->GetTypeId() != TYPEID_PLAYER) return; - caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_modifier.m_miscvalue : 0); + ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); } void Aura::HandleAuraTrackCreatures(bool apply, bool Real) @@ -2974,7 +2974,7 @@ void Aura::HandleModPossess(bool apply, bool Real) } } if(caster->GetTypeId() == TYPEID_PLAYER) - caster->SetUInt64Value(PLAYER_FARSIGHT,apply ? m_target->GetGUID() : 0); + ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); } void Aura::HandleModPossessPet(bool apply, bool Real) @@ -2989,15 +2989,13 @@ void Aura::HandleModPossessPet(bool apply, bool Real) return; if(apply) - { - caster->SetUInt64Value(PLAYER_FARSIGHT, m_target->GetGUID()); m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); - } else - { - caster->SetUInt64Value(PLAYER_FARSIGHT, 0); m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); - } + + ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); + ((Player*)caster)->SetCharm(apply ? m_target : NULL); + ((Player*)caster)->SetClientControl(m_target, apply ? 1 : 0); } void Aura::HandleModCharm(bool apply, bool Real) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 450e239e1..f1a12dbb2 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3202,7 +3202,7 @@ void Spell::EffectSummon(uint32 i) if(duration > 0) spawnCreature->SetDuration(duration); - spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID()); + spawnCreature->SetOwnerGUID(m_caster->GetGUID()); spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS, 0); spawnCreature->setPowerType(POWER_MANA); spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_caster->getFaction()); @@ -3212,7 +3212,7 @@ void Spell::EffectSummon(uint32 i) spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP, 0); spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000); - spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); + spawnCreature->SetCreatorGUID(m_caster->GetGUID()); spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); spawnCreature->InitStatsForLevel(level); @@ -3474,7 +3474,8 @@ void Spell::EffectAddFarsight(uint32 i) dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002); m_caster->AddDynObject(dynObj); MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj); - m_caster->SetUInt64Value(PLAYER_FARSIGHT, dynObj->GetGUID()); + if(m_caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_caster)->SetFarSight(dynObj->GetGUID()); } void Spell::EffectSummonWild(uint32 i) @@ -3631,14 +3632,14 @@ void Spell::EffectSummonGuardian(uint32 i) if(duration > 0) spawnCreature->SetDuration(duration); - spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID()); + spawnCreature->SetOwnerGUID(m_caster->GetGUID()); spawnCreature->setPowerType(POWER_MANA); spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0); spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0); spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0); spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0); - spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); + spawnCreature->SetCreatorGUID(m_caster->GetGUID()); spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); spawnCreature->InitStatsForLevel(level); @@ -4038,8 +4039,8 @@ void Spell::EffectSummonPet(uint32 i) NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE); } - NewSummon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID()); - NewSummon->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID()); + NewSummon->SetOwnerGUID(m_caster->GetGUID()); + NewSummon->SetCreatorGUID(m_caster->GetGUID()); NewSummon->SetUInt32Value(UNIT_NPC_FLAGS, 0); NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction); NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048); @@ -5659,8 +5660,8 @@ void Spell::EffectSummonCritter(uint32 i) return; } - critter->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID()); - critter->SetUInt64Value(UNIT_FIELD_CREATEDBY,m_caster->GetGUID()); + critter->SetOwnerGUID(m_caster->GetGUID()); + critter->SetCreatorGUID(m_caster->GetGUID()); critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction()); critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id); diff --git a/src/game/Totem.cpp b/src/game/Totem.cpp index 5c708bf0c..5f21b7cd9 100644 --- a/src/game/Totem.cpp +++ b/src/game/Totem.cpp @@ -128,10 +128,9 @@ void Totem::UnSummon() void Totem::SetOwner(uint64 guid) { - SetUInt64Value(UNIT_FIELD_SUMMONEDBY, guid); - SetUInt64Value(UNIT_FIELD_CREATEDBY, guid); - Unit *owner = GetOwner(); - if (owner) + SetCreatorGUID(guid); + SetOwnerGUID(guid); + if (Unit *owner = GetOwner()) { setFaction(owner->getFaction()); SetLevel(owner->getLevel()); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 0b6da451d..b23ad75c8 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -7151,12 +7151,15 @@ void Unit::SetPet(Pet* pet) // FIXME: hack, speed must be set only at follow if(pet) for(int i = 0; i < MAX_MOVE_TYPE; ++i) - pet->SetSpeed(UnitMoveType(i),m_speed_rate[i],true); + pet->SetSpeed(UnitMoveType(i), m_speed_rate[i], true); } -void Unit::SetCharm(Unit* charmed) +void Unit::SetCharm(Unit* pet) { - SetUInt64Value(UNIT_FIELD_CHARM,charmed ? charmed->GetGUID() : 0); + SetUInt64Value(UNIT_FIELD_CHARM, pet ? pet->GetGUID() : 0); + + if(GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->m_mover = pet ? pet : this; } void Unit::UnsummonAllTotems() @@ -10784,9 +10787,9 @@ Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget,uint32 spell_id) return NULL; } - pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, GetGUID()); - pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, GetGUID()); - pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,getFaction()); + pet->SetOwnerGUID(GetGUID()); + pet->SetCreatorGUID(GetGUID()); + pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, getFaction()); pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, spell_id); uint32 level = (creatureTarget->getLevel() < (getLevel() - 5)) ? (getLevel() - 5) : creatureTarget->getLevel(); diff --git a/src/game/Unit.h b/src/game/Unit.h index 73580cc77..63f2ffb5b 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -977,11 +977,14 @@ class MANGOS_DLL_SPEC Unit : public WorldObject DeathState getDeathState() { return m_deathState; }; virtual void setDeathState(DeathState s); // overwrited in Creature/Player/Pet - uint64 const& GetOwnerGUID() const { return GetUInt64Value(UNIT_FIELD_SUMMONEDBY); } + uint64 GetOwnerGUID() const { return GetUInt64Value(UNIT_FIELD_SUMMONEDBY); } + void SetOwnerGUID(uint64 owner) { SetUInt64Value(UNIT_FIELD_SUMMONEDBY, owner); } + uint64 GetCreatorGUID() const { return GetUInt64Value(UNIT_FIELD_CREATEDBY); } + void SetCreatorGUID(uint64 creator) { SetUInt64Value(UNIT_FIELD_CREATEDBY, creator); } uint64 GetPetGUID() const { return GetUInt64Value(UNIT_FIELD_SUMMON); } uint64 GetCharmerGUID() const { return GetUInt64Value(UNIT_FIELD_CHARMEDBY); } - uint64 GetCharmGUID() const { return GetUInt64Value(UNIT_FIELD_CHARM); } void SetCharmerGUID(uint64 owner) { SetUInt64Value(UNIT_FIELD_CHARMEDBY, owner); } + uint64 GetCharmGUID() const { return GetUInt64Value(UNIT_FIELD_CHARM); } uint64 GetCharmerOrOwnerGUID() const { return GetCharmerGUID() ? GetCharmerGUID() : GetOwnerGUID(); } uint64 GetCharmerOrOwnerOrOwnGUID() const @@ -1010,6 +1013,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void SetPet(Pet* pet); void SetCharm(Unit* pet); + bool isCharmed() const { return GetCharmerGUID() != 0; } CharmInfo* GetCharmInfo() { return m_charmInfo; } diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index df306a616..db79803f0 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -331,6 +331,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleMovementOpcodes(WorldPacket& recvPacket); void HandleSetActiveMoverOpcode(WorldPacket &recv_data); + void HandleMoveNotActiveMoverOpcode(WorldPacket &recv_data); void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data); void HandleRequestRaidInfoOpcode( WorldPacket & recv_data ); From 681cc6ecf478b4ef08c9b7ba712c39e5e5a9eda4 Mon Sep 17 00:00:00 2001 From: arrai Date: Sun, 16 Nov 2008 13:00:03 +0100 Subject: [PATCH 093/256] Fixed SMSG_RESURRECT_REQUEST for NPC resurrection --- src/game/Spell.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 0854606bd..2963925d5 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3006,16 +3006,19 @@ void Spell::SendChannelStart(uint32 duration) void Spell::SendResurrectRequest(Player* target) { - WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+2+4)); + // 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->GetName(); + + WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+strlen(sentName)+1+1+4)); data << uint64(m_caster->GetGUID()); - uint32 count = 1; - data << uint32(count); // amount of bytes to read + data << uint32(strlen(sentName)+1); - for(uint32 i = 0; i < count; ++i) - data << uint8(0); + data << sentName; + data << uint8(0); - data << uint8(0); - data << uint8(0); + data << uint32(m_caster->GetTypeId()==TYPEID_PLAYER ?0:1); target->GetSession()->SendPacket(&data); } From 4e76f1ac988f56fa688fff33f2cfbc4d031b14a9 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 16 Nov 2008 17:04:27 +0300 Subject: [PATCH 094/256] crash fix --- contrib/extractor/ad.exe | Bin 160768 -> 159744 bytes src/game/Map.cpp | 6 +++--- src/game/MovementHandler.cpp | 9 +++++---- src/game/Pet.cpp | 2 +- src/game/Player.cpp | 6 +++--- src/game/SpellAuras.cpp | 27 +++++++++++++++++++-------- src/game/Unit.cpp | 2 +- 7 files changed, 32 insertions(+), 20 deletions(-) diff --git a/contrib/extractor/ad.exe b/contrib/extractor/ad.exe index eec43be65dd74dbc0a1f1749a05323faf9944a3b..2ee6e5be85d4c352e9d96eb902139111bdaafacc 100755 GIT binary patch delta 16403 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 DJ(ahC delta 17050 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, obj->GetPositionY()); if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP ) { - sLog.outError("Map::Remove: Object " I64FMTD " have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); + sLog.outError("Map::Remove: Object " I64FMT " have invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord); return; } @@ -700,7 +700,7 @@ Map::Remove(T *obj, bool remove) if( !loaded(GridPair(cell.data.Part.grid_x, cell.data.Part.grid_y)) ) return; - DEBUG_LOG("Remove object " I64FMTD " from grid[%u,%u]", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y); + DEBUG_LOG("Remove object " I64FMT " from grid[%u,%u]", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y); NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); assert( grid != NULL ); @@ -954,7 +954,7 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce) if (i_InstanceId == 0) { if(GridMaps[gx][gy]) delete (GridMaps[gx][gy]); - // x and y are swaped + // x and y are swapped VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gy, gx); } else diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 13b987610..59d71c31b 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -364,7 +364,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) data.append(recv_data.contents(), recv_data.size()); GetPlayer()->SendMessageToSet(&data, false); - if(!_player->GetCharmGUID()) + if(!_player->GetCharmGUID()) // nothing is charmed { _player->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); _player->m_movementInfo = movementInfo; @@ -372,12 +372,13 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) } else { - if(mover->GetTypeId() != TYPEID_PLAYER) + if(mover->GetTypeId() != TYPEID_PLAYER) // unit, creature, pet, vehicle... { - mover->Relocate(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); + if(Map *map = mover->GetMap()) + map->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); mover->SetUnitMovementFlags(MovementFlags); } - else + else // player { ((Player*)mover)->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); ((Player*)mover)->m_movementInfo = movementInfo; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 4838ac098..d31585995 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -517,7 +517,7 @@ void Pet::Update(uint32 diff) { // unsummon pet that lost owner Unit* owner = GetOwner(); - if(!owner || !IsWithinDistInMap(owner, OWNER_MAX_DISTANCE) || 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; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 606d1e7bf..36fba438e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1222,7 +1222,7 @@ void Player::Update( uint32 p_time ) SendUpdateToOutOfRangeGroupMembers(); Pet* pet = GetPet(); - if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE)) + if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID()))) { RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true); return; @@ -15889,8 +15889,8 @@ void Player::RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent) m_guardianPets.erase(pet->GetGUID()); break; default: - if(GetPetGUID()==pet->GetGUID()) - SetPet(0); + if(GetPetGUID() == pet->GetGUID()) + SetPet(NULL); break; } diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index e775150e1..ab4e4544a 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2983,19 +2983,30 @@ void Aura::HandleModPossessPet(bool apply, bool Real) return; Unit* caster = GetCaster(); - if(!caster || caster->GetTypeId() != TYPEID_PLAYER) - return; - if(caster->GetPet() != m_target) + Pet *pet = caster->GetPet(); + if(!pet || (pet != m_target) || !caster || (caster->GetTypeId() != TYPEID_PLAYER)) return; if(apply) - m_target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); else - m_target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); + pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); - ((Player*)caster)->SetFarSight(apply ? m_target->GetGUID() : NULL); - ((Player*)caster)->SetCharm(apply ? m_target : NULL); - ((Player*)caster)->SetClientControl(m_target, apply ? 1 : 0); + ((Player*)caster)->SetFarSight(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); + } } void Aura::HandleModCharm(bool apply, bool Real) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 8344bc0da..05246322c 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -4133,7 +4133,7 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) m_Auras.erase(i); ++m_removedAuras; // internal count used by unit update - // Status unsummoned at aura remove + // Statue unsummoned at aura remove Totem* statue = NULL; if(IsChanneledSpell(Aur->GetSpellProto())) if(Unit* caster = Aur->GetCaster()) From 427fca695e92184b258136f6ebd58076f93c1b7d Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 16 Nov 2008 18:13:33 +0300 Subject: [PATCH 095/256] Compile fix --- src/game/MiscHandler.cpp | 14 ------- src/game/MovementHandler.cpp | 62 ++++++------------------------ src/game/ObjectMgr.cpp | 2 +- src/game/Opcodes.cpp | 4 +- src/game/Player.cpp | 16 +++++--- src/game/WorldSession.h | 2 - src/shared/Database/SQLStorage.cpp | 2 +- 7 files changed, 26 insertions(+), 76 deletions(-) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 7ed3b57cb..701d88929 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1669,20 +1669,6 @@ void WorldSession::HandleSpellClick( WorldPacket & recv_data ) _player->EnterVehicle(vehicle); } -void WorldSession::HandleDismissControlledVehicle( WorldPacket & recv_data ) -{ - //CHECK_PACKET_SIZE(recv_data, 8); - recv_data.hexlike(); // standard movement packet - - // using charm guid, because we don't have vehicle guid... - Vehicle *vehicle = ObjectAccessor::GetVehicle(_player->GetCharmGUID()); - - if(!vehicle) - return; - - _player->ExitVehicle(vehicle); -} - void WorldSession::HandleInspectAchievements( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data, 1); diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 59d71c31b..137130c34 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -170,6 +170,8 @@ void WorldSession::HandleMoveWorldportAckOpcode() void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { + sLog.outDebug("WORLD: Recvd %s (%u,0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode()); + CHECK_PACKET_SIZE(recv_data, 4+2+4+4+4+4+4); if(GetPlayer()->GetDontMove()) @@ -333,19 +335,13 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) DEBUG_LOG("FALLDAMAGE z=%f sz=%f pZ=%f FallTime=%d mZ=%f damage=%d SF=%d" , movementInfo.z, height, target->GetPositionZ(), movementInfo.fallTime, height, damage, safe_fall); } } + } - //handle fall and logout at the same time (logout started before fall finished) - /* outdated and create problems with sit at stun sometime - if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_ROTATE)) - { - target->SetStandState(PLAYER_STATE_SIT); - // Can't move - WorldPacket data( SMSG_FORCE_MOVE_ROOT, 12 ); - data.append(target->GetPackGUID()); - data << (uint32)2; - SendPacket( &data ); - } - */ + if(recv_data.GetOpcode() == CMSG_DISMISS_CONTROLLED_VEHICLE) + { + // using charm guid, because we don't have vehicle guid... + if(Vehicle *vehicle = ObjectAccessor::GetVehicle(_player->GetCharmGUID())) + _player->ExitVehicle(vehicle); } if(((MovementFlags & MOVEMENTFLAG_SWIMMING) != 0) != GetPlayer()->IsInWater()) @@ -413,6 +409,8 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) { + sLog.outDebug("WORLD: Recvd %s (%u,0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode()); + CHECK_PACKET_SIZE(recv_data, 8+4+4+2+4+4+4+4+4); /* extract packet */ @@ -545,46 +543,10 @@ void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_data) uint64 guid; recv_data >> guid; - if(_player->GetGUID() == guid) + if(_player->m_mover->GetGUID() != guid) { - if(_player->GetCharmGUID() == 0) - _player->m_mover = _player; + sLog.outError("HandleSetActiveMoverOpcode: incorrect mover guid: mover is " I64FMT " and should be " I64FMT, _player->m_mover->GetGUID(), guid); } - else - { - if(_player->GetCharmGUID() == guid) - { - if(IS_PLAYER_GUID(guid)) - { - if(Player *plr = objmgr.GetPlayer(guid)) - _player->m_mover = plr; - } - else if(IS_CREATURE_OR_PET_GUID(guid)) - { - if(Creature *creature = ObjectAccessor::GetCreatureOrPet(*_player, guid)) - _player->m_mover = creature; - } - else if(IS_VEHICLE_GUID(guid)) - { - if(Vehicle *vehicle = ObjectAccessor::GetVehicle(guid)) - _player->m_mover = vehicle; - } - else - { - sLog.outError("Unknown guid " I64FMT "in HandleSetActiveMoverOpcode", guid); - } - } - } - - WorldPacket data(SMSG_TIME_SYNC_REQ, 4); // new 2.0.x, enable movement - data << uint32(0x00000000); // on blizz it increments periodically - SendPacket(&data); -} - -void WorldSession::HandleMoveNotActiveMoverOpcode(WorldPacket &recv_data) -{ - sLog.outDebug("WORLD: Recvd CMSG_MOVE_NOT_ACTIVE_MOVER"); - recv_data.hexlike(); // normal movement packet } void WorldSession::HandleMountSpecialAnimOpcode(WorldPacket& /*recvdata*/) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 011d61eee..956c577cb 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -5330,7 +5330,7 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh) if(m_hiVehicleGuid>=0x00FFFFFF) { sLog.outError("Vehicle guid overflow!! Can't continue, shutting down server. "); - sWorld.m_stopEvent = true; + World::StopNow(ERROR_EXIT_CODE); } return m_hiVehicleGuid; case HIGHGUID_PLAYER: diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 4e6825606..91ae5a39c 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -747,7 +747,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*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::HandleMoveNotActiveMoverOpcode }, + /*0x2D1*/ { "CMSG_MOVE_NOT_ACTIVE_MOVER", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, /*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 }, @@ -1159,7 +1159,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*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 }, + /*0x46D*/ { "CMSG_DISMISS_CONTROLLED_VEHICLE", STATUS_LOGGEDIN, &WorldSession::HandleMovementOpcodes }, /*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 }, diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 36fba438e..e42e4ca40 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17521,6 +17521,10 @@ 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); @@ -18641,12 +18645,12 @@ void Player::EnterVehicle(Vehicle *vehicle) //vehicle->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); //vehicle->SetUInt32Value(UNIT_FIELD_BYTES_1, 0x02000000); - SetCharm(vehicle); - SetFarSight(vehicle->GetGUID()); + SetCharm(vehicle); // charm + SetFarSight(vehicle->GetGUID()); // set view - SetClientControl(vehicle, 1); + SetClientControl(vehicle, 1); // redirect controls to vehicle - WorldPacket data(SMSG_UNKNOWN_1181, 0); + WorldPacket data(SMSG_UNKNOWN_1181, 0); // shows vehicle UI? GetSession()->SendPacket(&data); data.Initialize(MSG_MOVE_TELEPORT_ACK, 30); @@ -18660,10 +18664,10 @@ void Player::EnterVehicle(Vehicle *vehicle) data << vehicle->GetPositionZ(); // z data << vehicle->GetOrientation(); // o // transport part - data << vehicle->GetGUID(); // transport guid + data << uint64(vehicle->GetGUID()); // transport guid data << float(0); // transport offsetX data << float(0); // transport offsetY - data << float(1); // transport offsetZ + data << float(2); // transport offsetZ data << float(0); // transport orientation data << uint32(getMSTime()); // transport time data << uint8(0); // seat diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index db79803f0..fcc5e6106 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -331,7 +331,6 @@ class MANGOS_DLL_SPEC WorldSession void HandleMovementOpcodes(WorldPacket& recvPacket); void HandleSetActiveMoverOpcode(WorldPacket &recv_data); - void HandleMoveNotActiveMoverOpcode(WorldPacket &recv_data); void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data); void HandleRequestRaidInfoOpcode( WorldPacket & recv_data ); @@ -553,7 +552,6 @@ class MANGOS_DLL_SPEC WorldSession void HandlePetSpellAutocastOpcode( WorldPacket& recvPacket ); void HandlePetCastSpellOpcode( WorldPacket& recvPacket ); void HandlePetLearnTalent( WorldPacket& recvPacket ); - void HandleDismissControlledVehicle( WorldPacket& recvPacket ); void HandleSetActionBar(WorldPacket& recv_data); diff --git a/src/shared/Database/SQLStorage.cpp b/src/shared/Database/SQLStorage.cpp index 74248b31c..5badcc2e1 100644 --- a/src/shared/Database/SQLStorage.cpp +++ b/src/shared/Database/SQLStorage.cpp @@ -33,7 +33,7 @@ const char CreatureInfoAddonInfofmt[]="iiiiiiis"; const char EquipmentInfofmt[]="iiii"; const char GameObjectInfosrcfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis"; const char GameObjectInfodstfmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiii"; -const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifsiiiiii"; +const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiisiiii"; const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiii"; const char PageTextfmt[]="isi"; const char SpellThreatfmt[]="ii"; From e69e5d83364c75a8d9a30e8984d9c4dd0d4c3ac8 Mon Sep 17 00:00:00 2001 From: arrai Date: Sun, 16 Nov 2008 16:41:21 +0100 Subject: [PATCH 096/256] Implemented ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS Use correct locale in SMSG_RESURRECT_REQUEST --- src/game/AchievementMgr.cpp | 24 ++++++++++++++++++++++++ src/game/Player.cpp | 3 +++ src/game/Spell.cpp | 6 +++--- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 60366d14e..9b4bf516e 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -26,6 +26,7 @@ #include "Database/DatabaseEnv.h" #include "GameEvent.h" #include "World.h" +#include "SpellMgr.h" const CriteriaCastSpellRequirement AchievementMgr::criteriaCastSpellRequirements[CRITERIA_CAST_SPELL_REQ_COUNT] = { @@ -396,6 +397,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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 @@ -426,6 +428,26 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui } 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; + } + } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); @@ -511,6 +533,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e42e4ca40..d232e08ed 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2782,7 +2782,10 @@ bool Player::addSpell(uint32 spell_id, bool active, bool learning, bool loading, } if(!loading) + { 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; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 2963925d5..1318d8293 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3009,16 +3009,16 @@ void Spell::SendResurrectRequest(Player* target) // 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->GetName(); + 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+4)); + 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 << uint32(m_caster->GetTypeId()==TYPEID_PLAYER ?0:1); + data << uint8(m_caster->GetTypeId()==TYPEID_PLAYER ?0:1); target->GetSession()->SendPacket(&data); } From dcb39d1512f96c63b23fa09b234188e9e55ded21 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 16 Nov 2008 21:15:37 +0300 Subject: [PATCH 097/256] Cleanup --- src/game/MiscHandler.cpp | 20 ---- src/game/MovementHandler.cpp | 139 ++++--------------------- src/game/Opcodes.h | 2 +- src/game/Player.cpp | 4 + src/game/Player.h | 8 +- src/game/SpellAuras.cpp | 1 + src/game/WaypointMovementGenerator.cpp | 32 ++---- src/game/WorldSession.cpp | 48 +++++++++ src/game/WorldSession.h | 4 +- 9 files changed, 94 insertions(+), 164 deletions(-) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 701d88929..e0ab13ee4 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1567,26 +1567,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"); diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 137130c34..8f74cdddd 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -170,70 +170,22 @@ void WorldSession::HandleMoveWorldportAckOpcode() void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { - sLog.outDebug("WORLD: Recvd %s (%u,0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode()); - - CHECK_PACKET_SIZE(recv_data, 4+2+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 */ + if(opcode == CMSG_MOVE_NOT_ACTIVE_MOVER) + { + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8); + uint64 old_mover_guid; + recv_data >> old_mover_guid; + } + 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+1); - - 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; - recv_data >> movementInfo.t_seat; - } - - if((MovementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) || (movementInfo.unk1 & 0x20)) - { - // 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()) @@ -247,7 +199,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) return; /* 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) @@ -288,7 +240,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) } // 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()) { // calculate total z distance of the fall // it is currently only used for the achievement system. It might be used in a more correct falldamage formula later @@ -337,14 +289,14 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) } } - if(recv_data.GetOpcode() == CMSG_DISMISS_CONTROLLED_VEHICLE) + if(opcode == CMSG_DISMISS_CONTROLLED_VEHICLE) { // using charm guid, because we don't have vehicle guid... if(Vehicle *vehicle = ObjectAccessor::GetVehicle(_player->GetCharmGUID())) _player->ExitVehicle(vehicle); } - 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) ); @@ -364,7 +316,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { _player->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); _player->m_movementInfo = movementInfo; - _player->SetUnitMovementFlags(MovementFlags); + _player->SetUnitMovementFlags(movementInfo.flags); } else { @@ -372,13 +324,13 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { if(Map *map = mover->GetMap()) map->CreatureRelocation((Creature*)mover, movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); - mover->SetUnitMovementFlags(MovementFlags); + mover->SetUnitMovementFlags(movementInfo.flags); } else // player { ((Player*)mover)->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o); ((Player*)mover)->m_movementInfo = movementInfo; - ((Player*)mover)->SetUnitMovementFlags(MovementFlags); + ((Player*)mover)->SetUnitMovementFlags(movementInfo.flags); } } @@ -411,21 +363,11 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) { sLog.outDebug("WORLD: Recvd %s (%u,0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode()); - CHECK_PACKET_SIZE(recv_data, 8+4+4+2+4+4+4+4+4); + CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8+4); /* extract packet */ uint64 guid; - uint16 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; - uint8 t_unk; - float s_pitch; - float j_unk1, j_sinAngle, j_cosAngle, j_xyspeed; - float u_unk1; + uint32 unk1; float newspeed; recv_data >> guid; @@ -436,47 +378,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+1); + recv_data >> unk1; // counter - recv_data >> t_GUID; - recv_data >> t_x >> t_y >> t_z >> t_o >> t_time >> t_unk; - } - if ((flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING2)) || (unkB & 0x20)) - { - // 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 >> u_unk1; // unknown - } + MovementInfo movementInfo; + ReadMovementInfo(recv_data, &movementInfo); // recheck CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+4); diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 8b20c7f74..078ef60d1 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1207,7 +1207,7 @@ enum Opcodes SMSG_SERVER_FIRST_ACHIEVEMENT = 0x498, SMSG_PET_LEARNED_SPELL = 0x499, // uint16 spellid, Your pet learned spell: %s SMSG_PET_UNLEARNED_SPELL = 0x49A, // uint16 spellid, Your pet unlearned %s - UMSG_UNKNOWN_1179 = 0x49B, // not found in client + CMSG_UNKNOWN_1179 = 0x49B, // movement opcode CMSG_UNKNOWN_1180 = 0x49C, // LUA: HearthAndResurrectFromArea SMSG_UNKNOWN_1181 = 0x49D, // empty SMSG_CRITERIA_REMOVE = 0x49E, // uint32, broadcasts EVENT_CRITERIA_UPDATE diff --git a/src/game/Player.cpp b/src/game/Player.cpp index d232e08ed..7f6dca38c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17537,6 +17537,10 @@ void Player::SendInitialPacketsBeforeAddToMap() 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 diff --git a/src/game/Player.h b/src/game/Player.h index 38f48c1e9..8f3f112ce 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -729,7 +729,7 @@ enum InstanceResetWarningType struct MovementInfo { // common - //uint32 flags; + uint32 flags; uint16 unk1; uint32 time; float x, y, z, o; @@ -749,17 +749,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 diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index ab4e4544a..341c79426 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3006,6 +3006,7 @@ void Aura::HandleModPossessPet(bool apply, bool Real) { pet->AttackStop(); pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); + pet->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); } } diff --git a/src/game/WaypointMovementGenerator.cpp b/src/game/WaypointMovementGenerator.cpp index b4f79b4be..4f17b0d38 100644 --- a/src/game/WaypointMovementGenerator.cpp +++ b/src/game/WaypointMovementGenerator.cpp @@ -42,8 +42,7 @@ alter table creature_movement add `wpguid` int(11) default '0'; #include //-----------------------------------------------// -void -WaypointMovementGenerator::LoadPath(Creature &c) +void WaypointMovementGenerator::LoadPath(Creature &c) { sLog.outDetail("LoadPath: loading waypoint path for creature %d,%d", c.GetGUIDLow(), c.GetDBTableGUIDLow()); @@ -59,26 +58,23 @@ WaypointMovementGenerator::LoadPath(Creature &c) for(uint32 i = 0; i < node_count-1; i++) i_hasDone[i] = false; - // to prevent a misbehaviour inside "update" + // to prevent a misbehavior inside "update" // update is always called with the next wp - but the wpSys needs the current // so when the routine is called the first time, wpSys gets the last waypoint // and this prevents the system from performing text/emote, etc i_hasDone[node_count - 1] = true; } -void -WaypointMovementGenerator::ClearWaypoints() +void WaypointMovementGenerator::ClearWaypoints() { i_path = NULL; } -void -WaypointMovementGenerator::Initialize() +void WaypointMovementGenerator::Initialize() { } -bool -WaypointMovementGenerator::Update(Creature &creature, const uint32 &diff) +bool WaypointMovementGenerator::Update(Creature &creature, const uint32 &diff) { if(!&creature) return true; @@ -103,7 +99,7 @@ WaypointMovementGenerator::Update(Creature &creature, const uint32 &di i_nextMoveTime.Update(diff); i_destinationHolder.UpdateTraveller(traveller, diff, false, true); - // creature has been stoped in middle of the waypoint segment + // creature has been stopped in middle of the waypoint segment if (!i_destinationHolder.HasArrived() && creature.IsStopped()) { if( i_nextMoveTime.Passed()) // Timer has elapsed, meaning this part controlled it @@ -213,14 +209,12 @@ void WaypointMovementGenerator::MovementInform(Creature &unit) } //----------------------------------------------------// -void -FlightPathMovementGenerator::LoadPath(Player &) +void FlightPathMovementGenerator::LoadPath(Player &) { objmgr.GetTaxiPathNodes(i_pathId, i_path,i_mapIds); } -uint32 -FlightPathMovementGenerator::GetPathAtMapEnd() const +uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const { if(i_currentNode >= i_mapIds.size()) return i_mapIds.size(); @@ -235,8 +229,7 @@ FlightPathMovementGenerator::GetPathAtMapEnd() const return i_mapIds.size(); } -void -FlightPathMovementGenerator::Initialize(Player &player) +void FlightPathMovementGenerator::Initialize(Player &player) { player.getHostilRefManager().setOnlineOfflineState(false); player.addUnitState(UNIT_STAT_IN_FLIGHT); @@ -251,7 +244,6 @@ FlightPathMovementGenerator::Initialize(Player &player) void FlightPathMovementGenerator::Finalize(Player & player) { - float x, y, z; i_destinationHolder.GetLocationNow(player.GetMapId(), x, y, z); player.SetPosition(x, y, z, player.GetOrientation()); @@ -271,8 +263,7 @@ void FlightPathMovementGenerator::Finalize(Player & player) } } -bool -FlightPathMovementGenerator::Update(Player &player, const uint32 &diff) +bool FlightPathMovementGenerator::Update(Player &player, const uint32 &diff) { if( MovementInProgress() ) { @@ -307,8 +298,7 @@ FlightPathMovementGenerator::Update(Player &player, const uint32 &diff) return false; } -void -FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() +void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport() { if(i_mapIds.empty()) return; diff --git a/src/game/WorldSession.cpp b/src/game/WorldSession.cpp index dc5226488..16ec9d3b9 100644 --- a/src/game/WorldSession.cpp +++ b/src/game/WorldSession.cpp @@ -547,3 +547,51 @@ void WorldSession::SetAccountData(uint32 type, time_t time_, std::string data) CharacterDatabase.escape_string(data); CharacterDatabase.PExecute("INSERT INTO account_data VALUES ('%u','%u','%u','%s')", acc, type, (uint32)time_, data.c_str()); } + +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 fcc5e6106..f2071fcb5 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -29,6 +29,7 @@ class MailItemsInfo; struct ItemPrototype; struct AuctionEntry; struct DeclinedName; +struct MovementInfo; class Creature; class Item; @@ -88,6 +89,8 @@ class MANGOS_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,...); @@ -587,7 +590,6 @@ class MANGOS_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); From 016ec89e83c1d2694d9c286ec9098d41296135c9 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 17 Nov 2008 01:45:11 +0300 Subject: [PATCH 098/256] VC90 projects for vmap extractor, added new mpq's --- .../vmap_assembler/VC90/vmap_assembler.vcproj | 455 ++++++++ contrib/vmap_assembler/vmap_assemblerVC90.sln | 19 + .../vmap_extractor_v2/vmapExtractor_VC90.sln | 19 + .../vmapExtractor_VC90.vcproj | 1000 +++++++++++++++++ .../vmapextract/vmapexport.cpp | 6 + src/shared/vmap/TileAssembler.cpp | 3 +- 6 files changed, 1500 insertions(+), 2 deletions(-) create mode 100644 contrib/vmap_assembler/VC90/vmap_assembler.vcproj create mode 100644 contrib/vmap_assembler/vmap_assemblerVC90.sln create mode 100644 contrib/vmap_extractor_v2/vmapExtractor_VC90.sln create mode 100644 contrib/vmap_extractor_v2/vmapExtractor_VC90.vcproj diff --git a/contrib/vmap_assembler/VC90/vmap_assembler.vcproj b/contrib/vmap_assembler/VC90/vmap_assembler.vcproj new file mode 100644 index 000000000..4710f92f1 --- /dev/null +++ b/contrib/vmap_assembler/VC90/vmap_assembler.vcproj @@ -0,0 +1,455 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/vmap_assembler/vmap_assemblerVC90.sln b/contrib/vmap_assembler/vmap_assemblerVC90.sln new file mode 100644 index 000000000..0aeab053c --- /dev/null +++ b/contrib/vmap_assembler/vmap_assemblerVC90.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmap_assembler", "VC90\vmap_assembler.vcproj", "{572FFF74-480C-4472-8ABF-81733BB4049D}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.ActiveCfg = Debug|Win32 + {572FFF74-480C-4472-8ABF-81733BB4049D}.Debug|Win32.Build.0 = Debug|Win32 + {572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.ActiveCfg = Release|Win32 + {572FFF74-480C-4472-8ABF-81733BB4049D}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/contrib/vmap_extractor_v2/vmapExtractor_VC90.sln b/contrib/vmap_extractor_v2/vmapExtractor_VC90.sln new file mode 100644 index 000000000..82d3e1509 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapExtractor_VC90.sln @@ -0,0 +1,19 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vmapExtractor", "vmapExtractor_VC90.vcproj", "{87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug Ansi Static|Win32 = Debug Ansi Static|Win32 + Release Ansi Static|Win32 = Release Ansi Static|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Debug Ansi Static|Win32.ActiveCfg = Debug Ansi Static|Win32 + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Debug Ansi Static|Win32.Build.0 = Debug Ansi Static|Win32 + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Release Ansi Static|Win32.ActiveCfg = Release Ansi Static|Win32 + {87335BBF-5DA8-4FEC-A51E-1FB948F2FFE9}.Release Ansi Static|Win32.Build.0 = Release Ansi Static|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/contrib/vmap_extractor_v2/vmapExtractor_VC90.vcproj b/contrib/vmap_extractor_v2/vmapExtractor_VC90.vcproj new file mode 100644 index 000000000..5d8cdea90 --- /dev/null +++ b/contrib/vmap_extractor_v2/vmapExtractor_VC90.vcproj @@ -0,0 +1,1000 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp b/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp index dfc7cddcf..0d2b39f8d 100644 --- a/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp +++ b/contrib/vmap_extractor_v2/vmapextract/vmapexport.cpp @@ -421,6 +421,10 @@ bool fillArchiveNameVector(std::vector& pArchiveNames) { // open expansion and common files printf("Opening data files from data directory.\n"); + sprintf(path, "%slichking.mpq", input_path); + pArchiveNames.push_back(path); + sprintf(path, "%scommon-2.mpq", input_path); + pArchiveNames.push_back(path); sprintf(path, "%sexpansion.mpq", input_path); pArchiveNames.push_back(path); sprintf(path, "%scommon.mpq", input_path); @@ -432,6 +436,8 @@ bool fillArchiveNameVector(std::vector& pArchiveNames) { for (std::vector::iterator i = locales.begin(); i != locales.end(); i++) { printf("Locale: %s\n", i->c_str()); + sprintf(path, "%s%s\\lichking-locale-%s.mpq", input_path, i->c_str(), i->c_str()); + pArchiveNames.push_back(path); sprintf(path, "%s%s\\expansion-locale-%s.mpq", input_path, i->c_str(), i->c_str()); pArchiveNames.push_back(path); sprintf(path, "%s%s\\locale-%s.mpq", input_path, i->c_str(), i->c_str()); diff --git a/src/shared/vmap/TileAssembler.cpp b/src/shared/vmap/TileAssembler.cpp index 30b5b28c0..2fd708137 100644 --- a/src/shared/vmap/TileAssembler.cpp +++ b/src/shared/vmap/TileAssembler.cpp @@ -73,12 +73,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); @@ -140,7 +140,6 @@ namespace VMAP //================================================================= bool TileAssembler::convertWorld() { - #ifdef _ASSEMBLER_DEBUG # ifdef _DEBUG ::g_df = fopen("../TileAssembler_debug.txt", "wb"); From 2eb34092e5cd7d9d7958c492ffc53f8a05f28134 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 17 Nov 2008 01:48:59 +0300 Subject: [PATCH 099/256] fix --- contrib/vmap_extractor_v2/vmapExtractor_VC90.vcproj | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/contrib/vmap_extractor_v2/vmapExtractor_VC90.vcproj b/contrib/vmap_extractor_v2/vmapExtractor_VC90.vcproj index 5d8cdea90..ed75735c4 100644 --- a/contrib/vmap_extractor_v2/vmapExtractor_VC90.vcproj +++ b/contrib/vmap_extractor_v2/vmapExtractor_VC90.vcproj @@ -1,9 +1,10 @@ - @@ -171,6 +171,8 @@ SuppressStartupBanner="true" ProgramDatabaseFile=".\bin\Win32\ReleaseAS/StormLib.pdb" SubSystem="1" + RandomizedBaseAddress="1" + DataExecutionPrevention="0" TargetMachine="1" /> - From 56c8d2549c3b3d4ec35f0f50c8a7532baae7f15a Mon Sep 17 00:00:00 2001 From: arrai Date: Tue, 18 Nov 2008 19:17:25 +0100 Subject: [PATCH 100/256] Implemented ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP --- src/game/AchievementMgr.cpp | 11 ++++++++++- src/game/CharacterHandler.cpp | 2 ++ src/shared/Database/DBCStructure.h | 7 +++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 9b4bf516e..6334728bd 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -447,7 +447,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, spellCount); break; } - + case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP: + { + // skip for login case + if(!miscvalue1) + continue; + SetCriteriaProgress(achievementCriteria, 1); + break; + } } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); @@ -535,6 +542,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 7dc621ef9..9bd5d9617 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -1159,6 +1159,8 @@ void WorldSession::HandleAlterAppearance( WorldPacket & recv_data ) _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 } diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index b5c7105ec..107f6bfb8 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -298,6 +298,13 @@ struct AchievementCriteriaEntry 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 From c0c0c9c776c43c81d45d1a20378ee19ea74fc41d Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 19 Nov 2008 00:59:14 +0300 Subject: [PATCH 101/256] barber shop race/gender checks, fly check for map 571 --- src/game/CharacterHandler.cpp | 4 +- src/game/ObjectMgr.cpp | 4 +- src/game/Player.cpp | 3 +- src/game/Spell.cpp | 19 ++- src/game/SpellEffects.cpp | 2 +- src/shared/Database/DBCStores.cpp | 4 +- src/shared/Database/DBCStructure.h | 258 +++++++++++++++-------------- src/shared/Database/DBCfmt.cpp | 2 +- 8 files changed, 158 insertions(+), 138 deletions(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 9bd5d9617..694f3c899 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -1126,12 +1126,12 @@ void WorldSession::HandleAlterAppearance( WorldPacket & recv_data ) BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair); - if(!bs_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) + 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); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 956c577cb..0c256ac7a 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -4703,14 +4703,14 @@ uint16 ObjectMgr::GetTaxiMount( uint32 id, uint32 team ) { if (team == ALLIANCE) { - mount_entry = node->alliance_mount_type; + mount_entry = node->MountCreatureID[1]; CreatureInfo const *ci = GetCreatureTemplate(mount_entry); if(ci) mount_id = ci->DisplayID_A; } if (team == HORDE) { - mount_entry = node->horde_mount_type; + mount_entry = node->MountCreatureID[0]; CreatureInfo const *ci = GetCreatureTemplate(mount_entry); if(ci) mount_id = ci->DisplayID_H; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index c6b6e8208..7836f23ef 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18376,7 +18376,8 @@ void Player::UpdateZoneDependentAuras( uint32 newZone ) { // remove new continent flight forms if( !isGameMaster() && - GetVirtualMapForMapAndZone(GetMapId(),newZone) != 530) + GetVirtualMapForMapAndZone(GetMapId(),newZone) != 530 && + GetVirtualMapForMapAndZone(GetMapId(),newZone) != 571) { RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED); RemoveSpellsCausingAura(SPELL_AURA_FLY); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 8a3f66f8a..88a6f4bd7 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4018,7 +4018,9 @@ uint8 Spell::CanCast(bool strict) if(int32(m_targets.getUnitTarget()->getLevel()) > CalculateDamage(i,m_targets.getUnitTarget())) return SPELL_FAILED_HIGHLEVEL; - };break; + + break; + } case SPELL_AURA_MOUNTED: { if (m_caster->IsInWater()) @@ -4051,7 +4053,9 @@ uint8 Spell::CanCast(bool strict) // can be casted at non-friendly unit or own pet/charm if(m_caster->IsFriendlyTo(m_targets.getUnitTarget())) return SPELL_FAILED_TARGET_FRIENDLY; - };break; + + break; + } case SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED: case SPELL_AURA_FLY: { @@ -4059,10 +4063,13 @@ uint8 Spell::CanCast(bool strict) if(m_caster->GetTypeId()==TYPEID_PLAYER) { if( !((Player*)m_caster)->isGameMaster() && - GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) != 530) + GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) != 530 && + !(GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) == 571 && ((Player*)m_caster)->HasSpell(54197))) return SPELL_FAILED_NOT_HERE; } - };break; + + break; + } case SPELL_AURA_PERIODIC_MANA_LEECH: { if (!m_targets.getUnitTarget()) @@ -4073,9 +4080,11 @@ uint8 Spell::CanCast(bool strict) if(m_targets.getUnitTarget()->getPowerType()!=POWER_MANA) return SPELL_FAILED_BAD_TARGETS; + break; } - default:break; + default: + break; } } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index bcb802b83..2722e477f 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4942,7 +4942,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->GetMapId() != 0 && caster->GetMapId() != 1 && caster->GetMapId() != 530) + if( caster->GetMapId() != 0 && caster->GetMapId() != 1 && caster->GetMapId() != 530 && caster->GetMapId() != 571) { SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here return; diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp index f3c15d518..cc817014c 100644 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -203,7 +203,7 @@ void LoadDBCStores(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)); } } @@ -546,7 +546,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/DBCStructure.h b/src/shared/Database/DBCStructure.h index 107f6bfb8..ab67dd96e 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -478,16 +478,16 @@ struct AreaTableEntry struct AreaTriggerEntry { - 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 extent x edge - float box_y; // 7 m_box_width extent y edge - float box_z; // 8 m_box_heigh extent z edge - float box_orientation; // 9 m_box_yaw 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 @@ -499,14 +499,14 @@ struct BankBagSlotPricesEntry struct BarberShopStyleEntry { uint32 Id; // 0 - //uint32 type; // 1 value 0 -> hair, value 2 -> facialhair + 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 unk3; // 36 values 1 and 0,75 - //uint32 race; // 37 race - //uint32 gender; // 38 0 -> male, 1 -> female + //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 }; @@ -590,20 +590,20 @@ struct ChrRacesEntry struct CreatureDisplayInfoEntry { - 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 + 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 @@ -618,15 +618,15 @@ struct CreatureFamilyEntry int32 petTalentType; // 8 m_petTalentType // 9 m_categoryEnumID char* Name[16]; // 10-25 m_name_lang - // 26 string flags, unused - // 27 m_iconFile unused + // 26 string flags + // 27 m_iconFile }; struct CreatureSpellDataEntry { - uint32 ID; // 0 m_ID - //uint32 spellId[4]; // 1-4 m_spells hunter pet learned spell (for later use) - //uint32 availability[4]; // 4-7 m_availability + uint32 ID; // 0 m_ID + //uint32 spellId[4]; // 1-4 m_spells[4] + //uint32 availability[4]; // 4-7 m_availability[4] }; struct DurabilityCostsEntry @@ -651,54 +651,48 @@ struct FactionEntry { uint32 ID; // 0 m_ID int32 reputationListID; // 1 m_reputationIndex - uint32 BaseRepRaceMask[4]; // 2-5 m_reputationRaceMask Base reputation race masks (see enum Races) - uint32 BaseRepClassMask[4]; // 6-9 m_reputationClassMask Base reputation class masks (see enum Classes) - int32 BaseRepValue[4]; // 10-13 m_reputationBase Base reputation values - uint32 ReputationFlags[4]; // 14-17 m_reputationFlags Default flags to apply - uint32 team; // 18 m_parentFactionID enum Team + 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, unused - //char* description[16]; // 36-51 m_description_lang unused - // 52 string flags, unused + // 35 string flags + //char* description[16]; // 36-51 m_description_lang + // 52 string flags }; struct FactionTemplateEntry { - uint32 ID; // 0 m_ID - uint32 faction; // 1 m_faction - uint32 factionFlags; // 2 m_flags specific flags for that faction - uint32 ourMask; // 3 m_factionGroup if mask set (see FactionMasks) then faction included in masked team - uint32 friendlyMask; // 4 m_friendGroup if mask set (see FactionMasks) then faction friendly to masked team - uint32 hostileMask; // 5 m_enemyGroup if mask set (see FactionMasks) then faction hostile to masked team - uint32 enemyFaction1; // 6 m_enemies[4] - uint32 enemyFaction2; // 7 - uint32 enemyFaction3; // 8 - uint32 enemyFaction4; // 9 - uint32 friendFaction1; // 10 m_friend[4] - 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 bool IsFriendlyTo(FactionTemplateEntry const& entry) const { - 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); } bool IsHostileTo(FactionTemplateEntry const& entry) const { - 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; } }; @@ -790,8 +784,18 @@ struct ItemEntry 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 @@ -814,19 +818,19 @@ struct ItemExtendedCostEntry struct ItemRandomPropertiesEntry { - 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 nameSufix flags + 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 m_ID - //char* name[16] // 1-16 m_name_lang unused - // 17, name flags, unused - // 18 m_internalName, unused + //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 }; @@ -909,13 +913,18 @@ struct MapEntry MapID==568 || MapID==309 || MapID==209 || MapID==534 || MapID==560 || MapID==509 || MapID==269; } + + 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 @@ -969,15 +978,15 @@ struct ScalingStatValuesEntry struct SkillLineEntry { uint32 id; // 0 m_ID - int32 categoryId; // 1 m_categoryID (index from SkillLineCategory.dbc) - //uint32 skillCostID; // 2 m_skillCostsID not used + int32 categoryId; // 1 m_categoryID + //uint32 skillCostID; // 2 m_skillCostsID char* name[16]; // 3-18 m_displayName_lang - // 19 string flags, not used - //char* description[16]; // 20-35 m_description_lang, not used - // 36 string flags, not used + // 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, not used + // 54 string flags // 55 m_canLink }; @@ -995,7 +1004,7 @@ struct SkillLineAbilityEntry uint32 learnOnGetSkill; // 9 m_acquireMethod uint32 max_value; // 10 m_trivialSkillLineRankHigh uint32 min_value; // 11 m_trivialSkillLineRankLow - //uint32 characterPoints[2]; // 12-13 m_characterPoints + //uint32 characterPoints[2]; // 12-13 m_characterPoints[2] }; struct SoundEntriesEntry @@ -1003,8 +1012,8 @@ struct SoundEntriesEntry uint32 Id; // 0 m_ID //uint32 Type; // 1 m_soundType //char* InternalName; // 2 m_name - //char* FileName[10]; // 3-12 m_File - //uint32 Unk13[10]; // 13-22 m_Freq + //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 @@ -1210,29 +1219,31 @@ struct SpellDurationEntry struct SpellItemEnchantmentEntry { - uint32 ID; // 0 m_ID - //uint32 charges; // 1 m_charges - uint32 type[3]; // 2-4 m_effect - uint32 amount[3]; // 5-7 m_effectPointsMin - //uint32 amount2[3] // 8-10 m_effectPointsMax - uint32 spellid[3]; // 11-13 m_effectArg - char* description[16]; // 14-30 m_name_lang + 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-30 m_name_lang[16] //uint32 descriptionFlags; // 31 name flags - uint32 aura_id; // 32 m_itemVisual - uint32 slot; // 33 m_flags - uint32 GemID; // 34 m_src_itemID - uint32 EnchantmentCondition; // 35 m_condition_id - //uint32 requiredSkill; // 36 m_requiredSkillID - //uint32 requiredSkillValue; // 37 m_requiredSkillRank + uint32 aura_id; // 32 m_itemVisual + uint32 slot; // 33 m_flags + uint32 GemID; // 34 m_src_itemID + uint32 EnchantmentCondition; // 35 m_condition_id + //uint32 requiredSkill; // 36 m_requiredSkillID + //uint32 requiredSkillValue; // 37 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 @@ -1284,38 +1295,37 @@ struct TalentTabEntry struct TaxiNodesEntry { - 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, unused - uint32 horde_mount_type; // 23 m_MountCreatureID[2] - 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; // 0 m_ID - uint32 from; // 1 m_FromTaxiNode - uint32 to; // 2 m_ToTaxiNode - uint32 price; // 3 m_Cost + uint32 ID; // 0 m_ID + uint32 from; // 1 m_FromTaxiNode + uint32 to; // 2 m_ToTaxiNode + uint32 price; // 3 m_Cost }; struct TaxiPathNodeEntry { - // 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 + // 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 diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 4ec736006..679e36d54 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -21,7 +21,7 @@ const char AchievementCriteriafmt[]="niiiiiiiixxxxxxxxxxxxxxxxxiixix"; const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxixxxxxxx"; const char AreaTriggerEntryfmt[]="niffffffff"; const char BankBagSlotPricesEntryfmt[]="ni"; -const char BarberShopStyleEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; +const char BarberShopStyleEntryfmt[]="nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii"; const char BattlemasterListEntryfmt[]="niiiiiiiiiiiixxxssssssssssssssssxx"; const char CharTitlesEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx"; From 4f559eb7e679a00b9355cf1527b45d30bfb404c8 Mon Sep 17 00:00:00 2001 From: arrai Date: Wed, 19 Nov 2008 15:02:39 +0100 Subject: [PATCH 102/256] Implemented ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION --- src/game/AchievementMgr.cpp | 9 +++++++++ src/game/Player.cpp | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 6334728bd..1bfd65a7f 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -455,6 +455,13 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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; + } } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); @@ -544,6 +551,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 7836f23ef..44cc37f4f 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -5691,7 +5691,7 @@ bool Player::ModifyOneFactionReputation(FactionEntry const* factionEntry, int32 } } } - + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION); SendFactionState(&(itr->second)); return true; @@ -5757,6 +5757,7 @@ bool Player::SetOneFactionReputation(FactionEntry const* factionEntry, int32 sta SetFactionAtWar(&itr->second,true); SendFactionState(&(itr->second)); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION); return true; } return false; From b9e695b72785a41f45c773e37a3a9c4e1d373ebb Mon Sep 17 00:00:00 2001 From: arrai Date: Wed, 19 Nov 2008 19:56:17 +0100 Subject: [PATCH 103/256] Implemented ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION --- src/game/AchievementMgr.cpp | 14 ++++++++++++++ src/game/Player.cpp | 2 ++ src/game/Player.h | 1 + 3 files changed, 17 insertions(+) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 1bfd65a7f..d26c53cf0 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -462,6 +462,18 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui 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); + } + } if(IsCompletedCriteria(achievementCriteria)) CompletedCriteria(achievementCriteria); @@ -553,6 +565,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 44cc37f4f..02a915e18 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -5692,6 +5692,7 @@ 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; @@ -5758,6 +5759,7 @@ bool Player::SetOneFactionReputation(FactionEntry const* factionEntry, int32 sta SendFactionState(&(itr->second)); GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION); + GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION); return true; } return false; diff --git a/src/game/Player.h b/src/game/Player.h index 50a7081b8..7354ffe56 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1715,6 +1715,7 @@ class MANGOS_DLL_SPEC Player : public Unit FactionStateList m_factions; ForcedReactions m_forcedReactions; + FactionStateList const& GetFactionStateList() { return m_factions; } uint32 GetDefaultReputationFlags(const FactionEntry *factionEntry) const; int32 GetBaseReputation(const FactionEntry *factionEntry) const; int32 GetReputation(uint32 faction_id) const; From 8e32c8ca76aa9d88b5dabade6f6a71e1f2990a64 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 19 Nov 2008 16:39:09 +0300 Subject: [PATCH 104/256] Speedup map checks --- src/game/Player.cpp | 5 ++--- src/game/Spell.cpp | 5 ++--- src/game/SpellEffects.cpp | 3 ++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 02a915e18..90219e524 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18378,9 +18378,8 @@ void Player::SetClientControl(Unit* target, uint8 allowMove) void Player::UpdateZoneDependentAuras( uint32 newZone ) { // remove new continent flight forms - if( !isGameMaster() && - GetVirtualMapForMapAndZone(GetMapId(),newZone) != 530 && - GetVirtualMapForMapAndZone(GetMapId(),newZone) != 571) + uint32 v_map = GetVirtualMapForMapAndZone(GetMapId(), newZone); + if( !isGameMaster() && v_map != 530 && v_map != 571) { RemoveSpellsCausingAura(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED); RemoveSpellsCausingAura(SPELL_AURA_FLY); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 88a6f4bd7..f2a858dfc 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4062,9 +4062,8 @@ uint8 Spell::CanCast(bool strict) // 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 && - !(GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) == 571 && ((Player*)m_caster)->HasSpell(54197))) + uint32 v_map = GetVirtualMapForMapAndZone(m_caster->GetMapId(), m_caster->GetZoneId()); + if( !((Player*)m_caster)->isGameMaster() && v_map != 530 && !(v_map == 571 && ((Player*)m_caster)->HasSpell(54197))) return SPELL_FAILED_NOT_HERE; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 2722e477f..e39a16c4f 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4942,7 +4942,8 @@ 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->GetMapId() != 0 && caster->GetMapId() != 1 && caster->GetMapId() != 530 && caster->GetMapId() != 571) + uint32 mapid = caster->GetMapId(); + if( mapid != 0 && mapid != 1 && mapid != 530 && mapid != 571 && mapid != 609) { SendCastResult(SPELL_FAILED_NO_DUELING); // Dueling isn't allowed here return; From 600a596796beeeda0ed71e127a30578db42fb8da Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 21 Nov 2008 20:09:11 +0100 Subject: [PATCH 105/256] Fixed titles, PLAYER__FIELD_KNOWN_TITLES is now 128 bits long --- src/game/MiscHandler.cpp | 4 ++-- src/game/Player.cpp | 24 +++++++++++++++++++++--- src/game/Player.h | 4 ++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index e0ab13ee4..917867993 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1482,9 +1482,9 @@ void WorldSession::HandleChooseTitleOpcode( WorldPacket & recv_data ) recv_data >> title; // -1 at none - if(title > 0 && title < 64) + if(title > 0 && title < 128) { - if(!GetPlayer()->HasFlag64(PLAYER__FIELD_KNOWN_TITLES,uint64(1) << title)) + if(!GetPlayer()->HasTitle(title)) return; } else diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 90219e524..90d96ec28 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -12382,7 +12382,7 @@ void Player::RewardQuest( Quest const *pQuest, uint32 reward, Object* questGiver if(pQuest->GetCharTitleId()) { if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId())) - SetFlag64(PLAYER__FIELD_KNOWN_TITLES, (uint64(1) << titleEntry->bit_index)); + SetTitle(titleEntry); } // Send reward mail @@ -14003,7 +14003,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) // note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded if(uint32 curTitle = GetUInt32Value(PLAYER_CHOSEN_TITLE)) { - if(!HasFlag64(PLAYER__FIELD_KNOWN_TITLES,uint64(1) << curTitle)) + if(!HasTitle(curTitle)) SetUInt32Value(PLAYER_CHOSEN_TITLE,0); } @@ -14615,7 +14615,7 @@ void Player::_LoadQuestStatus(QueryResult *result) if(pQuest->GetCharTitleId()) { if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(pQuest->GetCharTitleId())) - SetFlag64(PLAYER__FIELD_KNOWN_TITLES, (uint64(1) << titleEntry->bit_index)); + SetTitle(titleEntry); } } @@ -18734,3 +18734,21 @@ void Player::ExitVehicle(Vehicle *vehicle) // only for flyable vehicles? CastSpell(this, 45472, true); // Parachute } + +bool Player::HasTitle(uint32 bitIndex) +{ + if (bitIndex > 128) + return false; + + uint32 fieldIndexOffset = bitIndex/32; + uint32 flag = 1 << (bitIndex%32); + return HasFlag(PLAYER__FIELD_KNOWN_TITLES+fieldIndexOffset, flag); +} + +void Player::SetTitle(CharTitlesEntry const* title) +{ + uint32 fieldIndexOffset = title->bit_index/32; + uint32 flag = 1 << (title->bit_index%32); + SetFlag(PLAYER__FIELD_KNOWN_TITLES+fieldIndexOffset, flag); +} + diff --git a/src/game/Player.h b/src/game/Player.h index 7354ffe56..9bb7d7f3d 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2068,6 +2068,10 @@ class MANGOS_DLL_SPEC Player : public Unit DeclinedName const* GetDeclinedNames() const { return m_declinedname; } AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } + bool HasTitle(uint32 bitIndex); + bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); } + void SetTitle(CharTitlesEntry const* title); + protected: /*********************************************************/ From d1b5944000c87fd720f9a711042a85fec9d16d1d Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 21 Nov 2008 20:10:28 +0100 Subject: [PATCH 106/256] Implemented achievement rewards --- src/game/AchievementMgr.cpp | 110 +++++++++++++++++++++++++++++++++++- src/game/AchievementMgr.h | 9 +++ 2 files changed, 118 insertions(+), 1 deletion(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index d26c53cf0..97c0d51d2 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -78,6 +78,68 @@ const CriteriaCastSpellRequirement AchievementMgr::criteriaCastSpellRequirements {6662, 31261, 0, 0} }; +const AchievementReward AchievementMgr::achievementRewards[ACHIEVEMENT_REWARD_COUNT] = + { + // achievementId, horde titleid, alliance titleid, itemid + {45, 0, 0, 43348}, + {46, 78, 78, 0}, + {230, 72, 72, 0}, + {456, 139, 139, 0}, + {614, 0, 0, 44223}, + {619, 0, 0, 44224}, + {714, 47, 47, 0}, + {762, 130, 130, 0}, + {870, 127, 126, 0}, + {871, 144, 144, 0}, + {876, 0, 0, 43349}, + {907, 48, 48, 0}, + {913, 74, 74, 0}, + {942, 79, 79, 0}, + {943, 79, 79, 0}, + {945, 131, 131, 0}, + {948, 130, 130, 0}, + {953, 132, 132, 0}, + {978, 81, 81, 0}, + {1015, 77, 77, 0}, + {1021, 0, 0, 40643}, + {1038, 75, 75, 0}, + {1039, 76, 76, 0}, + {1163, 128, 128, 0}, + {1174, 82, 82, 0}, + {1175, 72, 72, 0}, + {1250, 0, 0, 40653}, + {1400, 120, 120, 0}, + {1402, 122, 122, 0}, + {1516, 83, 83, 0}, + {1563, 84, 84, 0}, + {1656, 124, 124, 0}, + {1657, 124, 124, 0}, + {1658, 129, 129, 0}, + {1681, 125, 125, 43300}, + {1682, 125, 125, 43300}, + {1683, 133, 133, 0}, + {1684, 133, 133, 0}, + {1691, 134, 134, 0}, + {1692, 134, 134, 0}, + {1693, 135, 135, 0}, + {1707, 135, 135, 0}, + {1784, 84, 84, 0}, + {1793, 137, 137, 0}, + {1956, 0, 0, 43824}, + {2051, 140, 140, 0}, + {2054, 121, 121, 0}, + {2096, 0, 0, 44430}, + {2136, 0, 0, 0},// <- TODO: find item for spell 59961 + {2137, 0, 0, 0},// <- TODO: find item for spell 60021 + {2138, 0, 0, 0},// <- TODO: find item for spell 59976 + {2143, 0, 0, 44178}, + {2144, 0, 0, 0},// <- TODO: find item for spell 60024 + {2145, 0, 0, 0},// <- TODO: find item for spell 60024 + {2186, 141, 141, 0}, + {2187, 142, 142, 0}, + {2188, 143, 143, 0} + }; + AchievementMgr::AchievementMgr(Player *player) { m_player = player; @@ -666,7 +728,53 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) objmgr.allCompletedAchievements.insert(achievement->ID); UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT); - // TODO: reward titles and items + + // reward items and titles + AchievementReward const* reward = NULL; + for (uint32 i=0; iID) + { + reward = &achievementRewards[i]; + break; + } + } + + if (reward) + { + sLog.outString("achiev %u, title= %u, %u", reward->achievementId, reward->titleId[0], reward->titleId[1]); + uint32 titleId = reward->titleId[GetPlayer()->GetTeam() == HORDE?0:1]; + if(CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId)) + GetPlayer()->SetTitle(titleEntry); + + if (reward->itemId) + { + ItemPrototype const *pProto = objmgr.GetItemPrototype( reward->itemId ); + + if(!pProto) + { + GetPlayer()->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + + ItemPosCountVec dest; + uint32 no_space = 0; + uint8 msg = GetPlayer()->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, reward->itemId, 1, &no_space ); + + if( msg != EQUIP_ERR_OK ) + { + GetPlayer()->SendEquipError( msg, NULL, NULL ); + return; + } + Item* pItem = GetPlayer()->StoreNewItem( dest, reward->itemId, true); + + if(!pItem) + { + GetPlayer()->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL ); + return; + } + } + } } void AchievementMgr::SendAllAchievementData() diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index 98f0fb904..35e07570d 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -24,6 +24,7 @@ #include "Database/DatabaseEnv.h" #define CRITERIA_CAST_SPELL_REQ_COUNT 46 +#define ACHIEVEMENT_REWARD_COUNT 57 struct CriteriaProgress { @@ -46,6 +47,13 @@ struct CriteriaCastSpellRequirement uint8 playerRace; }; +struct AchievementReward +{ + uint32 achievementId; + uint32 titleId[2]; + uint32 itemId; +}; + typedef UNORDERED_MAP CriteriaProgressMap; typedef UNORDERED_MAP CompletedAchievementMap; @@ -88,5 +96,6 @@ class AchievementMgr CriteriaProgressMap m_criteriaProgress; CompletedAchievementMap m_completedAchievements; static const CriteriaCastSpellRequirement criteriaCastSpellRequirements[]; + static const AchievementReward achievementRewards[]; }; #endif From 4908ecd7c806eb5c0b5a9114f011c88832fd85c0 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 22 Nov 2008 09:03:15 +0300 Subject: [PATCH 107/256] Fixed vmaps extraction. Patch provided by andstan. Untested. Please test and report bugs to http://mangos.lighthouseapp.com --- .../vmap_extractor_v2/vmapextract/model.cpp | 143 ++------ contrib/vmap_extractor_v2/vmapextract/model.h | 27 +- .../vmapextract/modelheaders.h | 316 +++--------------- 3 files changed, 77 insertions(+), 409 deletions(-) diff --git a/contrib/vmap_extractor_v2/vmapextract/model.cpp b/contrib/vmap_extractor_v2/vmapextract/model.cpp index 7dca7841d..31962a001 100644 --- a/contrib/vmap_extractor_v2/vmapextract/model.cpp +++ b/contrib/vmap_extractor_v2/vmapextract/model.cpp @@ -1,11 +1,7 @@ -//#include "common.h" #include "model.h" -//#include "world.h" #include #include -//int globalTime = 0; - Model::Model(std::string &filename) : filename(filename) { } @@ -24,43 +20,24 @@ bool Model::open() } memcpy(&header, f.getBuffer(), sizeof(ModelHeader)); - if(header.nBoundingTriangles > 0) { - -#if 0 - animated = isAnimated(f); - if(animated) + if(header.nBoundingTriangles > 0) + { + f.seek(0); + f.seekRelative(header.ofsBoundingVertices); + vertices = new Vec3D[header.nBoundingVertices]; + f.read(vertices,header.nBoundingVertices*12); + for (uint32 i=0; iofsIndex); - uint16 *triangles = (uint16*)(f.getBuffer() + view->ofsTris); - - nIndices = view->nTris; - indices = new uint16[nIndices]; - for (size_t i = 0; i0) { - ModelBoneDef &bb = bo[verts[i].bones[b]]; - if (bb.translation.type || bb.rotation.type || bb.scaling.type || (bb.flags&8)) { - if (bb.flags&8) { - // if we have billboarding, the model will need per-instance animation - ind = true; - } - animGeometry = true; - break; - } - } - } - } - - if (animGeometry) animBones = true; - else { - for (size_t i=0; i 0; - - bool animMisc = header.nCameras>0 || // why waste time, pretty much all models with cameras need animation - header.nLights>0 || // same here - header.nParticleEmitters>0 || - header.nRibbonEmitters>0; - - if (animMisc) animBones = true; - - // animated colors - if (header.nColors) { - ModelColorDef *cols = (ModelColorDef*)(f.getBuffer() + header.ofsColors); - for (size_t i=0; i0) + fwrite(&nIndexes, sizeof(uint32), 1, output); + if(nIndexes >0) { - fwrite(indices, sizeof(unsigned short), nIdexes, output); + fwrite(indices, sizeof(unsigned short), nIndexes, output); } fwrite("VERT",4, 1, output); wsize = sizeof(int) + sizeof(float) * 3 * nVertices; @@ -178,7 +86,7 @@ bool Model::ConvertToVMAPModel(char * outfilename) fwrite(&nVertices, sizeof(int), 1, output); if(nVertices >0) { - for(int vpos=0; vpos class Model; @@ -18,18 +17,14 @@ Vec3D fixCoordSystem(Vec3D v); class Model { public: + ModelHeader header; - ModelAnimation *anims; - int *globalSequences; public: - bool animGeometry,animTextures,animBones; - bool animated; - bool isAnimated(MPQFile &f); - ModelVertex *origVertices; - Vec3D *vertices, *normals; - uint16 *indices; + uint32 offsBB_vertices, offsBB_indices; + Vec3D *BB_vertices, *vertices; + uint16 *BB_indices, *indices; size_t nIndices; bool open(); @@ -38,12 +33,6 @@ public: public: bool ok; - bool ind; - - float rad; - float trans; - bool animcalc; - int anim, animtime; Model(std::string &filename); ~Model(); @@ -59,15 +48,9 @@ public: Model *model; int id; - Vec3D pos, rot; unsigned int d1, scale; - - float frot,w,sc; - - int light; - Vec3D ldir; - Vec3D lcol; + float w,sc; ModelInstance() {} ModelInstance(MPQFile &f,const char* ModelInstName,const char*MapName, FILE *pDirfile); diff --git a/contrib/vmap_extractor_v2/vmapextract/modelheaders.h b/contrib/vmap_extractor_v2/vmapextract/modelheaders.h index 7d5e800e7..c35b983c1 100644 --- a/contrib/vmap_extractor_v2/vmapextract/modelheaders.h +++ b/contrib/vmap_extractor_v2/vmapextract/modelheaders.h @@ -15,289 +15,67 @@ struct ModelHeader { uint8 version[4]; uint32 nameLength; uint32 nameOfs; - uint32 type; - + uint32 type; uint32 nGlobalSequences; uint32 ofsGlobalSequences; uint32 nAnimations; uint32 ofsAnimations; - uint32 nC; - uint32 ofsC; - uint32 nD; - uint32 ofsD; - uint32 nBones; - uint32 ofsBones; - uint32 nF; - uint32 ofsF; - + uint32 nAnimationLookup; + uint32 ofsAnimationLookup; + uint32 nBones; + uint32 ofsBones; + uint32 nKeyBoneLookup; + uint32 ofsKeyBoneLookup; uint32 nVertices; uint32 ofsVertices; uint32 nViews; - uint32 ofsViews; - uint32 nColors; uint32 ofsColors; - uint32 nTextures; uint32 ofsTextures; - - uint32 nTransparency; // H + uint32 nTransparency; uint32 ofsTransparency; - uint32 nI; // always unused ? - uint32 ofsI; - uint32 nTexAnims; // J - uint32 ofsTexAnims; - uint32 nK; - uint32 ofsK; - - uint32 nTexFlags; - uint32 ofsTexFlags; - uint32 nY; - uint32 ofsY; - - uint32 nTexLookup; - uint32 ofsTexLookup; - - uint32 nTexUnitLookup; // L - uint32 ofsTexUnitLookup; - uint32 nTransparencyLookup; // M - uint32 ofsTransparencyLookup; - uint32 nTexAnimLookup; - uint32 ofsTexAnimLookup; - - float floats[14]; - - uint32 nBoundingTriangles; - uint32 ofsBoundingTriangles; - uint32 nBoundingVertices; - uint32 ofsBoundingVertices; - uint32 nBoundingNormals; - uint32 ofsBoundingNormals; - - uint32 nO; - uint32 ofsO; - uint32 nP; - uint32 ofsP; - uint32 nQ; - uint32 ofsQ; - uint32 nLights; // R - uint32 ofsLights; - uint32 nCameras; // S - uint32 ofsCameras; - uint32 nT; - uint32 ofsT; - uint32 nRibbonEmitters; // U - uint32 ofsRibbonEmitters; - uint32 nParticleEmitters; // V - uint32 ofsParticleEmitters; - + uint32 nTextureanimations; + uint32 ofsTextureanimations; + uint32 nTexReplace; + uint32 ofsTexReplace; + uint32 nRenderFlags; + uint32 ofsRenderFlags; + uint32 nBoneLookupTable; + uint32 ofsBoneLookupTable; + uint32 nTexLookup; + uint32 ofsTexLookup; + uint32 nTexUnits; + uint32 ofsTexUnits; + uint32 nTransLookup; + uint32 ofsTransLookup; + uint32 nTexAnimLookup; + uint32 ofsTexAnimLookup; + float floats[14]; + uint32 nBoundingTriangles; + uint32 ofsBoundingTriangles; + uint32 nBoundingVertices; + uint32 ofsBoundingVertices; + uint32 nBoundingNormals; + uint32 ofsBoundingNormals; + uint32 nAttachments; + uint32 ofsAttachments; + uint32 nAttachLookup; + uint32 ofsAttachLookup; + uint32 nAttachments_2; + uint32 ofsAttachments_2; + uint32 nLights; + uint32 ofsLights; + uint32 nCameras; + uint32 ofsCameras; + uint32 nCameraLookup; + uint32 ofsCameraLookup; + uint32 nRibbonEmitters; + uint32 ofsRibbonEmitters; + uint32 nParticleEmitters; + uint32 ofsParticleEmitters; }; -// block B - animations -struct ModelAnimation { - uint32 animID; - uint32 timeStart; - uint32 timeEnd; - - float moveSpeed; - - uint32 loopType; - uint32 flags; - uint32 d1; - uint32 d2; - uint32 playSpeed; // note: this can't be play speed because it's 0 for some models - - Vec3D boxA, boxB; - float rad; - - int16 s[2]; -}; - - -// sub-block in block E - animation data -struct AnimationBlock { - int16 type; // interpolation type (0=none, 1=linear, 2=hermite) - int16 seq; // global sequence id or -1 - uint32 nRanges; - uint32 ofsRanges; - uint32 nTimes; - uint32 ofsTimes; - uint32 nKeys; - uint32 ofsKeys; -}; - -// block E - bones -struct ModelBoneDef { - int32 animid; - int32 flags; - int16 parent; // parent bone index - int16 geoid; - // new int added to the bone definitions. Added in WoW 2.0 - int32 unknown; - AnimationBlock translation; - AnimationBlock rotation; - AnimationBlock scaling; - Vec3D pivot; -}; - -struct ModelTexAnimDef { - AnimationBlock trans, rot, scale; -}; - -struct ModelVertex { - Vec3D pos; - uint8 weights[4]; - uint8 bones[4]; - Vec3D normal; - Vec2D texcoords; - int unk1, unk2; // always 0,0 so this is probably unused -}; - -struct ModelView { - uint32 nIndex, ofsIndex; // Vertices in this model (index into vertices[]) - uint32 nTris, ofsTris; // indices - uint32 nProps, ofsProps; // additional vtx properties - uint32 nSub, ofsSub; // materials/renderops/submeshes - uint32 nTex, ofsTex; // material properties/textures - int32 lod; // LOD bias? -}; - - -/// One material + render operation -struct ModelGeoset { - uint16 d1; // mesh part id? - uint16 d2; // ? - uint16 vstart; // first vertex - uint16 vcount; // num vertices - uint16 istart; // first index - uint16 icount; // num indices - uint16 d3; // number of bone indices - uint16 d4; // offset into bone index list - uint16 d5; // ? - uint16 d6; // root bone? - Vec3D v; - float unknown[4]; // Added in WoW 2.0? -}; - -/// A texture unit (sub of material) -struct ModelTexUnit{ - // probably the texture units - // size always >=number of materials it seems - uint16 flags; // Flags - uint16 order; // ? - uint16 op; // Material this texture is part of (index into mat) - uint16 op2; // Always same as above? - int16 colorIndex; // color or -1 - uint16 flagsIndex; // more flags... - uint16 texunit; // Texture unit (0 or 1) - uint16 d4; // ? (seems to be always 1) - uint16 textureid; // Texture id (index into global texture list) - uint16 texunit2; // copy of texture unit value? - uint16 transid; // transparency id (index into transparency list) - uint16 texanimid; // texture animation id -}; - -// block X - render flags -struct ModelRenderFlags { - uint16 flags; - uint16 blend; -}; - -// block G - color defs -struct ModelColorDef { - AnimationBlock color; - AnimationBlock opacity; -}; - -// block H - transp defs -struct ModelTransDef { - AnimationBlock trans; -}; - -struct ModelTextureDef { - uint32 type; - uint32 flags; - uint32 nameLen; - uint32 nameOfs; -}; - -struct ModelLightDef { - int16 type; - int16 bone; - Vec3D pos; - AnimationBlock ambColor; - AnimationBlock ambIntensity; - AnimationBlock color; - AnimationBlock intensity; - AnimationBlock attStart; - AnimationBlock attEnd; - AnimationBlock unk1; -}; - -struct ModelCameraDef { - int32 id; - float fov, farclip, nearclip; - AnimationBlock transPos; - Vec3D pos; - AnimationBlock transTarget; - Vec3D target; - AnimationBlock rot; -}; - - -struct ModelParticleParams { - float mid; - uint32 colors[3]; - float sizes[3]; - int16 d[10]; - float unk[3]; - float scales[3]; - float slowdown; - float rotation; - float f2[16]; -}; - -struct ModelParticleEmitterDef { - int32 id; - int32 flags; - Vec3D pos; - int16 bone; - int16 texture; - int32 nZero1; - int32 ofsZero1; - int32 nZero2; - int32 ofsZero2; - int16 blend; - int16 type; - int16 s1; - int16 s2; - int16 cols; - int16 rows; - AnimationBlock params[10]; - ModelParticleParams p; - AnimationBlock unk; -}; - - -struct ModelRibbonEmitterDef { - int32 id; - int32 bone; - Vec3D pos; - int32 nTextures; - int32 ofsTextures; - int32 nUnknown; - int32 ofsUnknown; - AnimationBlock color; - AnimationBlock opacity; - AnimationBlock above; - AnimationBlock below; - float res, length, unk; - int16 s1, s2; - AnimationBlock unk1; - AnimationBlock unk2; -}; - - #pragma pack(pop) From 5b5e266c17f29b75fdf4705de3ba7c1264748d21 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 22 Nov 2008 09:04:10 +0300 Subject: [PATCH 108/256] Misc fixes --- src/game/Player.cpp | 4 ++++ src/game/SharedDefines.h | 2 +- src/game/SpellAuras.cpp | 2 +- src/game/Unit.h | 16 ++++++++-------- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 90d96ec28..640898df1 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -7968,6 +7968,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; } diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 14072c790..38fc9b959 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -1555,7 +1555,7 @@ enum CreatureFamily enum CreatureTypeFlags { - CREATURE_TYPEFLAGS_TAMEBLE = 0x0001, + CREATURE_TYPEFLAGS_TAMEABLE = 0x0001, CREATURE_TYPEFLAGS_HERBLOOT = 0x0100, CREATURE_TYPEFLAGS_MININGLOOT = 0x0200 }; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 344ce5afb..64c6afaf0 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3017,7 +3017,7 @@ void Aura::HandleModPossessPet(bool apply, bool Real) { pet->AttackStop(); pet->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE); - pet->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + pet->SetUnitMovementFlags(MOVEMENTFLAG_NONE); } } diff --git a/src/game/Unit.h b/src/game/Unit.h index a25bef2f3..3b585b4f3 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -163,14 +163,14 @@ enum SheathState // byte (1 from 0..3) of UNIT_FIELD_BYTES_2 enum UnitBytes2_Flags { - UNIT_BYTE2_FLAG_PVP = 0x01, - UNIT_BYTE2_FLAG_UNK1 = 0x02, - UNIT_BYTE2_FLAG_FFA_PVP = 0x04, - UNIT_BYTE2_FLAG_UNK3 = 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_PVP = 0x01, + UNIT_BYTE2_FLAG_UNK1 = 0x02, + UNIT_BYTE2_FLAG_FFA_PVP = 0x04, + UNIT_BYTE2_FLAG_SANCTUARY = 0x08, + UNIT_BYTE2_FLAG_AURAS = 0x10, // show positive auras as positive, and allow its dispel + 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 From f0fbe808372e46e65926f93b0bbc430cce7419ad Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 22 Nov 2008 18:20:03 +0300 Subject: [PATCH 109/256] Compile fix --- src/game/Creature.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/Creature.h b/src/game/Creature.h index dbe3e9248..af97e517e 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -216,7 +216,7 @@ struct CreatureInfo bool isTameable() const { - return type == CREATURE_TYPE_BEAST && family != 0 && (type_flags & CREATURE_TYPEFLAGS_TAMEBLE); + return type == CREATURE_TYPE_BEAST && family != 0 && (type_flags & CREATURE_TYPEFLAGS_TAMEABLE); } }; From 688693029ec559deb29af78bbe5c49e675f1462d Mon Sep 17 00:00:00 2001 From: arrai Date: Sat, 22 Nov 2008 18:13:14 +0100 Subject: [PATCH 110/256] Fixed unintialized Creature::m_isVehicle --- src/game/Creature.cpp | 5 +++-- src/game/Creature.h | 1 - src/game/Pet.h | 1 - src/game/Player.h | 1 - src/game/Unit.h | 3 ++- src/game/Vehicle.cpp | 1 - 6 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 50bbdc146..191071310 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -96,11 +96,12 @@ Unit(), i_AI(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_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_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0), m_AlreadyCallAssistence(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),m_creatureInfo(NULL), m_DBTableGuid(0) { + m_regenTimer = 200; m_valuesCount = UNIT_END; for(int i =0; i<4; ++i) diff --git a/src/game/Creature.h b/src/game/Creature.h index af97e517e..a23e8be1d 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -625,7 +625,6 @@ class MANGOS_DLL_SPEC Creature : public Unit bool m_isTotem; // set only in Totem::Totem 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/Pet.h b/src/game/Pet.h index f43a1e305..29c96dcc1 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -221,7 +221,6 @@ class Pet : public Creature 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; PetType m_petType; int32 m_duration; // time until unsummon (used mostly for summoned guardians and not used for controlled pets) diff --git a/src/game/Player.h b/src/game/Player.h index 9bb7d7f3d..e724bd9a4 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2236,7 +2236,6 @@ class MANGOS_DLL_SPEC Player : public Unit bool m_DailyQuestChanged; time_t m_lastDailyQuestTime; - uint32 m_regenTimer; uint32 m_breathTimer; uint32 m_drunkTimer; uint16 m_drunk; diff --git a/src/game/Unit.h b/src/game/Unit.h index 3b585b4f3..46cedc379 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -493,7 +493,7 @@ enum UnitFlags2 UNIT_FLAG2_FEIGN_DEATH = 0x00000001, UNIT_FLAG2_COMPREHEND_LANG = 0x00000008, UNIT_FLAG2_FORCE_MOVE = 0x00000040, - UNIT_FLAG2_UNKNOWN1 = 0x00000800 + UNIT_FLAG2_REGENERATE_POWER = 0x00000800 }; /// Non Player Character flags @@ -1370,6 +1370,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject uint32 m_unit_movement_flags; uint32 m_reactiveTimer[MAX_REACTIVE]; + uint32 m_regenTimer; private: void SendAttackStop(Unit* victim); // only from AttackStop(Unit*) diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp index 374b083fc..12acd640e 100644 --- a/src/game/Vehicle.cpp +++ b/src/game/Vehicle.cpp @@ -82,7 +82,6 @@ bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, u SetVehicleId(vehicleId); SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - SetUInt32Value(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_UNKNOWN1); //SetUInt32Value(UNIT_FIELD_BYTES_1, 0x02000001); //SetUInt32Value(UNIT_FIELD_BYTES_2, 0x00000001); SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); From d869f3b5ea1ac33698305bc5f33118aded8f2d47 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 22 Nov 2008 22:45:39 +0300 Subject: [PATCH 111/256] Changed some BG constants --- src/game/BattleGround.h | 2 -- src/game/BattleGroundMgr.h | 4 ++-- src/game/Player.cpp | 10 +++++----- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index b18f49581..f1afbca3f 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -129,8 +129,6 @@ struct BattleGroundObjectInfo uint32 spellid; }; -#define MAX_QUEUED_PLAYERS_MAP 7 - enum BattleGroundTypeId { BATTLEGROUND_AV = 1, diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 193e5f430..981468dd2 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -30,9 +30,9 @@ typedef std::map BattleGroundSet; //typedef std::map BattleGroundQueueSet; typedef std::deque BGFreeSlotQueueType; -#define MAX_BATTLEGROUND_QUEUES 7 // for level ranges 10-19, 20-29, 30-39, 40-49, 50-59, 60-69, 70+ +#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_TYPES 9 // each BG type will be in array +#define MAX_BATTLEGROUND_TYPES 12 // each BG type will be in array struct PlayerQueueInfo { diff --git a/src/game/Player.cpp b/src/game/Player.cpp index ab8e41750..65219c89b 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17923,15 +17923,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; @@ -17942,8 +17942,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, ... } From 13c5aea02841616f621c8fced708c6af5338a454 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 22 Nov 2008 23:52:31 +0300 Subject: [PATCH 112/256] Updated vmap extractor bin's --- .../vmap_assembler.exe | Bin 184320 -> 293888 bytes .../vmapextract_v2.exe | Bin 233472 -> 217088 bytes src/game/Map.cpp | 2 -- 3 files changed, 2 deletions(-) diff --git a/contrib/vmap_extract_assembler_bin/vmap_assembler.exe b/contrib/vmap_extract_assembler_bin/vmap_assembler.exe index 5cb08f770aa039d87b8968e658301f1e848ce869..a6ef74dc086d0d0fade554ece7bf68143becfe7c 100644 GIT binary patch literal 293888 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�}Rz0xE2IjfTLl8BVBwBEq)V! z7S$avwYB#JJhfTf_@(L_?}q-E#BY5!NZ}DA(m=F^i!IWwK!Fo091Q%0e?32Gzd4z?=WvVimx;%&~ z5NWBZQ0mLx+U>9F%3oLBftVV_UQvC6 z<~4=va3?0&^f}yF9sJ`aB&DXqBpdF$AoRyg1~OkOXdn8*@JHzj9ayRDNQdigzLIa% z!8zODRqiMl7n?m%%CWesLm_K(2p$KrK&Si$uqQ3w3LM#iHOE_l;~lnok%U7Fz>n&kzWFA7)DE2DttYDJ#^ks+ zy)|Xu^f=3&Fe?ck1TE!Rb}S#==BM9+cmt)lcCN3#^!%b$Md;R2Qgl^N^~d3YJlIBa zv7!!P)ViYTF2hpeI=~pr{C;7bZ-20SG=H8>FgF6h_INh_ypH|)^A^CRX8d{j1b-g? zrX?KwdGG#JiQ?fplaA?vbcCGm$oA)Tc>X-oF_?(^?;WxTV{-j@B#??RY={254*L*3 z?!%vlc@JUI{{?@ZBEj|Nb-4b#Z=GrUc^&G{W7`$u6%P3GIv!Fms5={oU*aUdp9gS# z{=AMHe;(0Vp(F78c}%I1<^75-FieLmK})0f^8lgx^UjC(^t0b1|LtQxl7jBdjwkDV z_&#+{AM06Aem&Ofd)P% zjKem>Y9(_oFmRxdk`@Lbm`Dp43qh z)b|6(3V=`$A4t*?f(NyODpQAcOj@moch05%ntSwj=zy?}WSI*7HN^1SB0s-XyZAyV zL?&1w8Cgf!=wPb1{fWw&T8nrE<*%cPxf?qJ(C(pOpKc1a$Z8a1yh&tjGV++&VSfzc z)Z!~(3Thxjq(xdxgJd_h|5LpBA&v|noZzLC)yB_~Rg^h^Kg)hqw`LHQz>uAf$-_nl zO_5MkUh(!ehIPA=i!7Fv(b~iMlJetYG<%es*A^&#iTsH>#b$l_<0CqLnjT)3+4ZEno|m7b-Z|wFh)(%7wqzS5(65WI5ZsVkO3Fi9`TJxZ2`=?=R$}*mZuo!#`K z|K=2$x(w@KxQ_|#ISCWSuobe13GZ?G;oghMvdJv0;XQwclG@hLiDYHOCO##by66RL z;BT^_1HZHL8Rugv{||I&R8BT@BO|eqzk7@BQH!OCfF*990T-bgGGr^Pc5KGpo!GHd zouO#SU9=Y*t&Z&weVCm$`&7G$NzRf(*iTfJntlqjpJYQPOed5ovmHJ;E5@@_ja=iE zVyY=+YuT+!#;`=daX5^a)5LMq)OG=DE^Kn6Ix51B!$G4&4@)==U1%v<+e7qvef^a= z@;NPEY%4_0GHpN6Uut(GA8EnBWA<;Q>5qh>8EE zw7DEJXhg~(j+TgK^47e8%Ki$nS@)JHfQs96ayW5qI$1h}`h*rZUIbyWFAS=MgOc^2 z2zcZ?spc@%1w=kXUa~<@E3uKkfqC__OXMcVBaNC`i&0RvB{uRYP&dg|Dygv*2KHy# zVy@f>CquGfH69r@!@q{Q_>^o~hhNG>yMa%pPupRi9xSY%YT$f8=;-Ryw%hW=#*|iQ&Cwrjo_9#4qwq48FRH{`T2Dj$U4ohTYO83vj9*adI-NngM$@t7u+uZi5dZA*AQCu##9PF2xkN7kGaS&ikZ9j3F$=S-0U zP^7?G9d#NQ3mBC>{=!?AjAtsW474A>isZGQXDa{pbyj)6RB<$}5YRPCKGK1a;NtpK z@{d5^j&ic>_T(c=(3lf%u93xK~G)LBzJsdZIlKL1d_mvhXm7Jb~u$tfVlN#klpC(On{2 zpb2a_-jJS&deQZ#E=^v;ZPqf*oS$H7gFuR7Esx3*@ZezU!-*`%S`GgUAhYAkH0W=c zb~TLluQBbr4mGrI>}xffxC(!WO&YU%i)}_X{wye$Ak_|Vdk2ATKE1-L4}16_V=ZU) zBPtDlW!X@^^2g{neES#S{g$T^M)}|~mW_U-@EbqiL5fqFb2KOEX(&uWF@TpLteakH z%w>5r0T1+{<_tf>`|4ub$H|cnZs0hPPQ`1j(cta)j%3_ZbZu)pl^h~)+XKquM&0X_ zXF4$pzDf2W&%lrV#ozy^`l&0r-MFVy5!ohr6x`N!DApPS-2sjYNomSZTc%)#bgFpR zPTg}OfB~G_X`DOpwW!h|y+|{}yjJR&FJCTK!3f>lrg5UWtrJ-*@4l)fLB1XG7M?xf ziheurYFm%_2daAQ`^RSXu3UYV^W}?oTndOY6lLaP<#TC$2n)d|^MR;XqoAulqhF2( zE_~2@p3r3Dywn8o{A=x#_BI2HzAoPS!>C=D_Dj~M;g5|1{QwLr`5NS{I|{tAhp0&* z;XrlEhTrG^2EBY#``PU>9>ay49e*0Hqc@(W$B$|s!UR+_AkTq?(|v_72JnXtQJ(565z`xf21Btj)@9{e~seH#FWFQWJHlnCO7$Y#nl&ovqPO!RyHgB*KUT?mo(jEk`y z@UZ20J6(*Wvg!BGF=%>tGSD^ll{U7^u~-tbjQz-#WF&3u)BC_cRr(^}V!Xx7Z@XNC zsWUFdDUjk=$U7v31r);v)j|j8z(CvO3=oz}(JXP7Wj7HRzzeA;syrn;zk57y2DeV8mtJ-`=-Gh;yw{K`31zR z>rfDtUUy}pemF3%I8z_4h???babsU0Ig2id@?^9eE$J?qz=M>i?+?_eA>S`Q-^x|1 zn?9g!rG3H?!g(8jmz*BzI~;7G(P;?ZDo5N9qos=)uAxlK9%*{Kpywz3^jtiO#O-#S z6;#4{VN!VXq=yZ<}9Ow3l+3^d;SFkYkFoxdR?epF<8 z`Iy!xcW4_K{iy6{U1t5_EKLt6|0d`jeP+rJfI?N2_VV`ap!aUrNK6KJQ7=;_kxS7|nm0}|!6o!#VK4YAn#E{hL>LXpGPDDpIH}#< z)K}71#H4Q`2|S0;-~7HcIpM{`A8-cW42A=z%(R^q?L{j#FWu~I8fd<5+XIqNjlB11 z;xrQg@8MI0*szSJa^hQV(({A)t~62{(LB?Q6ps(LK}W#I5Pp2eK>z~`I4sW~1vp^P z4>R3$$xyG)zenn#yvI&S6+^s-SV`-v*#T7+voXvVQk>RPNe>6qI8bgz>es#m zarly97mP>OFDw^Czkk1?6m>q%eg)+Z*H<$fNHrZpWnH>m!b3=z}Y}V7!i#LbE76-00il;08*EeL=9I+6!5ZcO-7t zkY%L1w!#1wmJT@?b85CYbi1lzJlm;<5540dJ|QfpHvt4N?l=>%jQx)oeAcB1jQJ-c zmf3xWeRJ@nTR^WJuUBcr^8FACh*(A_4&#{FcEuqI2IOmptq`eoV<7$(G+%6SAgA&p zw>a2J_7=zESX01=ptlY=4K1m|y_@8g4p|2Bd|Mn?L3M|*R5ripF8|zNBxz^1I6jNF ze{qY$qgOqzw3mB$;Do0jIgM60B!B-MInoQS&+sF5I1E8&FB94x&pVjgZCmvNKflvyA$49YGWaJ2G$>$u&SJABf9&Z&FWD5D@C-a zOO#oCh}%chwq!&fXQ2-}b~a?NE}i`d)yMt~J-TM;9FT5BYY&&s9>UK9LO6D?sc)5O z53x-1jItS*wko*AIiJ#22|o#*0Fo=G{4Q?53;vzltI| z_WzarxYDScJ9qT`xWhp2;7Yjkpol=Q>~}v7#MZ6*agaa2wr@YKR6hCJ(N%PJKkiQW z1hZ81eeTDVj$%lXViw+DQ(=B-sgaQwKe4Ct$W~YZ z-s+suhnWw&Yr)3te88+%7sJzmRZCzHxr>nUo5r-O+G5TJJU$+(JXv(q^8x6;!lJ^% z;}e5CK2fYp$1{InHMkB#hd3$_m6tFe?s-5=KDBFK}Ej_+;jI>Md{`bZG>o7c5iG|*tbS^?4TdltbYAdN>>Z`o6 zl}5nUVyZ8o6a}zo$^EG5I8l_Bi3sWgwi;O3t}Zo-R|n1!=nl}lAR5d=tl-~aom>u_ z#%AZ$u43&b)~=BPEg440a~+F9l0Z4@#^yUYP(eseFLk@x^E1X_LLr;r*5>rmztQ(Y zt#;c4tyZ)?@^=^z2vUKrr%fa_mB|t4bgA`sa2TAEZQ&dv4EO>6*7@aA=_vYr7Xs?B zO_(uOyVO{P81JI7S}4VBE+@beP|uNWL%Q)W-SRiA`$?-)Lm&YUh^!MflqUq@U7oSp zfm+TIN7#NHZY`9FYo@wAgSRJ zR7`B-Z=mjz_Po&3pJHK6*!_sD*-0fVZu5}9kPX7r{$fG+Crm#Gpy|6Ew15p6CCPK4 zVd#ceUAfn&v++x)zWWiUfq$cJ!4vS@R|)F%H3^c@MqZh1 zh<#XD8GAo~^HQVeJ300oy?+o-*R?7`e+&}#Oi%smu0Ni2_gBS9wtj{FAX1>5W;~L! z;Nfto5DM-{kL0J2rXES|pMkAh2E~%>ai=}7`;oriK-1Mg(u_ni@_t;4Papj^@Ry!< zT?J||@p1Zu_&EOcm?;2e`W@C(P{+e7O}a9Z>Ns9}9D+$OoPEW|l>vFZYgvQ=XNZqu zJM|N2!yUp$#>X`vJKK7sp&2p=`ZtBheF@7gkG%RrrbM7mlKjqvITX z{73Lwy88GfI<%3Ia%Mfu;_r+His!#GY|brKoMQHQpg!$m?T|gS;5}%2o*Wvo&ng&l z7vjDb(p;|nO=f=x?(1ZT;_z&^S32PXHZ`O2X@o3*3#o!3N|8CV0%DT)f{Q$m_P}*J zRoq#f3{-?`dzb8)3%8CcsY&&GoXwFeK3w3k1DRKKr*!$v;zr!zD1eN=m#W_J}Db%{^y@^T4m$Iz{T zw#riNFf!0Ky^K#NrJ{PYJ<|+4Jg@h;|6&V3g>l%@b!*%tp6gaKp<(#Pg9FF3XYTr8 z9u|3QJP$DYjT><62LVd%O)*UfW3=1l6!Yi%bvW2!MsCJCH#1(eHj4d%of%R&_fLCd zC2W=S$gzV{E@KHdHcD_2TNS)qJ?_Bi!!Nq~+k}?8D5Wqu&4Iwvk(54}H?0+}k)r!> zocq8{Q8{O?(jxX|7?h$X15br-2rQMHPjxMJrkjQKP=@U%-f!)7IPpBtn!xM3{{y$dp0(BhKxkg95~mgdvQOvTzm8EEO}QIGNYC z1~wbPt~=5nk)xVY8JZptwZ2)Ve6%vtFmf%dn9^#pyHgJiY61Rgy+_j-1De5K z&A2C>(XSc&HBC0l|3Lh=S!>9A6i;h(F?BuGu3+ytojrVB6Jp zWHt9C)!uat$vkv6r*#T%5i*u#>*3r!SH#LSXi!lzXXliH%~83gP#q_3$@vfDq3Xm; z)kl0)d*Orub=VUa#*V6=cB_(LVF`2IWDJ`3jNNY@%x>ew4CpqwkD>)H_ds+Nb)4&2 z>*!-MBGG_6lQY>amtrVhg$qp53os15dY3WDROpA-%}c(S)Qt<}0O;v<1K}!&mL;3? z20SJ!RTL(}rgwnO9616*bsKvgCxCtIVS2dyem{peP4psow)+7-U-8B*y5UiX?o*xx$&)W>P2+-v3oXl?Asaf&%`oL`jnoHaf?4*OLBX$YBt zm&%7GuT<`39tTdupw|i7D^EqP^T_UtOv-l2mbs31S0^#@=eHU8lj!%N5B>3Qt8ho2 ztRC{MQ>(a6U9p8J+sUH{h=W5-{b-LdGSaa+0SPYSq+nvS>nfQ-RR+;((AzLgt7Jzj z@rR}#OIBl_X_c;M&0Nu%pE(^(?qfxpgR@pJlfmR>MOz)H!-}@rjyGqoXwAB!t=1JS z#`xa&YF*J*((AXLx5t zS<5wHtDCSaWi2!EOJwTvp!&y6Mt5pvW6EmOvJa$_mZYpDn)K~-(xQ~L$TYA{-g}Po z+bZ9LBf^2p@D~2nxo(vvSgyQzl<7%6^bsDpIHkA0ph3v_I<3M*y$*Z*0**=h$ldL&0xp$#*uBAm zl-}O*06`P$-_E65Zwp5CfwM17Mz-MgOiy2|T|z%O9r!=_huRYGq9^JH5e@wz{Tq?N z7_PU1zrnH;KZWPvA40oM_}8xBmpbn+L0vNvM9p3%?s)_@fjswutL_h&C3Wb(ZjkUV25m{BB=n;C@?e}=Btaujw>`#9H!9j7_l zPKT_8T|N>fjN!7JI&PsdkN5yrVpC~MP9446Bo}r&R$2o?g&mf~B;SQQzNMn7)Zm@v z1B%mH=o>_p90Ufy#J*vqNVFoJmS?+?&WxL3qcSp$|>YT*2qF2)d9)Y z;cr$Yl^$zia-mnrg=S=-EipMEr;rohg5_~d)CK!(tVCHuRWT3by`vFzp5Pp98i2fQ zA6ck7Dr-hBRHRom801aYAzE+nHtq*OlP+)bxn=0|keLem~x7b4FQ&M9vy*1gn21(v54~rO8yWmW{iyYHnL?jWCG(0O@;jsJ}`dSM-~Fcr{)xb zkIoywo~J!x%EI*WWe}+iU&Tm?Y5vW<@@U|%E~aVH05`DI1Kz&rBy;hR)}wG$vnM9c zt|q2gKG}3Oeu-)RHJIj8Qny0WnC8By2k4DZ09=ChWBP5|$Zvzw>uief^GdTZ{Q}DD z7t<3>h5cjtuSfbwfU5qNVw`pp%TxPrqH)PN;9oNbd@{S+ z={Znno9N4dNdTQnd6GLlZPsd5qC*0P1-#>{-Jw~lu>ut(mLbzflAvs9grE}hgPjFa1h31?Y zW6Rt-U|iEt|CsgkYnkhnTzz4>O`!Fik)$Jm_GJFyuHS5Im_)d>tZ+=~Z3BYu5{~ z6uI-s4?wJ-b2{6;;q_aYctVX)0$js#9l%5@!*bO+AP{~!94krx!*~IfSf)&&T!g!N zGSN)h9`ld)@+XhXSAQlEjQeUjBZa=pYIs#lP?OR()!;6fd`c9SpvWBTKNDe1*T{qZMA8IbO=h&7OnO|KuXf1vNQ7C^~Oq_J`WAN|`L z9yl5NV;?-f?hN%vqmmuNJ!Z5yTJ(6=!R4(&DI027S}GoKwd6l0wq| zMD|pV-v0a05k_r)S0=-2|F^!RkSyCz`(sC^A9p{9_qAOC8wdz)s|-TcaIz6{s!!%9 zCeND;&jM@DO2#I;6X9njKfbX4hn>d4A55kW%7Bop1Cj5 zUnHHM=5N9cEkvbWi1CSrUpQGfFZOE=gWEEC&)g||^+Dt7&y+uTjh3IYZAwAAOi8y& z$jra&_PHnZnk!X|QG$HNTWGiij%I{-WtJ=7u*i6k7Kld7*IO$YGYs6$3)z=^FGyVV zz0M7cNQhqviDIMLJcoIo5}2WtjyFUy7t5OaDF09y7avtko|T-A`54MIjsS8RUfj2J z!hYso1ubxNg2wZuQFem4Pb`D7bbC6#;pBu_xc400>m&mOS@{qZ*ptaE;-OOiD!xun zMz-^QnWDdQWuWU6E*?GQdV*BYx7#i~oQrlj2Y-Nq?a~9^W7K%Xx|l%7m;XwOK5dG^ zXUw7@xsLBfx@!EYUtVLNozq9XUkn$Vjl5qhKl^^MqkoPLv*oroe$d{%WJN=FcPm$> zNmedZhqZ?3?1O($|7E~U-y!Mv5#KZX_ilPf9{gDvf;9cP>qXI1*sVZStX$q^rlAMD z4|AyKc`J0z-a7+gT6fFwnUw{m&-!4-K=>G4Rc&!go7@T(6aiR0?2DY$CP zlL20RPu=;Ug>ce2GxADN*wYh6w$~QePA5xF5w_>bL+n^$NR-VXynoJpCRWNbeyP}IcTNBG`t=Wk=fW^I|FWV4Q!q_ruR5?nK$carv|v0p8iBzbJ0^=#+wVGg=fVF ziW0k(p$0G^#j*vp5G}FQ>Z4n|v|(pa!*`L*{fVbxp*YqSjG=(wVn?+ z@#mqwQy#Z+mqHByu3Aux>VPg>ZP94`1?JTA_&5^oxsCq?ex(yR1t`J2CAR)|_!%JR zFQLSYhf}y(CEOYE?zuI)$Jp*+xOHG@WKCnF5AF1!ox@2^Xd9nsVKkNr$B-9cW-<{D zxr4Pih%7cXe@yRz$m)FuJEHKOQ^&zw<@^JD*ws8nptj1c$FN}zW2QNkuhmXXUm=w# z6_%%1>K${@D{m0hOV4|oh|YMkT}3k2*1ls}i!@`hwrP8l(H@85FBg_?Xt~roT7>PP z1cUrA>oM9?Xe=yM{zAO5PzxRBhd(Sw4^NSwj!lN?YMtltBVDuQ};ioNsJB? z3m0Q7X8@|w8W{N{Kzr6!FDQdv|6)178_N&Z>sTHgM)weWCGPj7Cb{=F|L!OB0Q>K6 z?n-PfCUF^Y%t?*O{g1k&O?>bQ=g*?^y>JKfP&rF@S2&k(lx? zbv9bw_02izK}NrVd~sKVASVuFp%X_rSSXj$I>vy)K7DvjD{cRRw5DbxHslTTRfrs3 zb_#7(Ne;o<2!0&G(HdM_NfmU+^&sR3J0s7uKBO2r{+H^bU-|QbJR=1ap0k-$^*41B z3`$Z>{gAvjpxR*OKkMHPQ4$1HF02IFjTR457XGl&3N=&8W@q|h| z2P$W!Q<;xcY}@R`HzN0rVm|r!4gGzTW=44d9{ay(i`fbo@Ne`*e78`ezlicP^ZjyW zz8Ci|#{xAnM8H{yr4wy2CW>NilDxM<8D^a{zpLGO@oS$@GW5r<9mW)VAJfFI`687h zf_Y^8+5$A5YT&O1RGi@^*J(0;HTh^a`DRV#uZgt~X?PI3R{@ia__gb`0DraK+qg#; zy&$7jGx)0+FQqehKVhnYzoyA%nTjT%c<3rSB7W^}-*w~H5T=dATt5>_oQ%H|uTZ2` ztABY?%yAe*C-09*^D1s6H))%Z7IhqIBr+d#j62Ou2ET8M3=Q6z$&7%TvD{?*i8W>* z!)apW8mECpQG*!}l*{C8&1^TBf6z>%o<=@sm&@t$XqUu$T4#f)BT@iVP}0hW4@1Rk zT4O4&^(qgdNz{4}rSRwTrt(Ttxmivym78TFD%(mb@-<4!c-S6?dv;;4#h1bM!M9Ce za>Q5A-obY~d3khvm0lk0j}CQZh&$@bt-L_5AwEO#Q$fw?h_8j{nZ9PO5$FwEpvtz1 z@?tGHLTztUMUYo;enV zQn@qo5*|o6KLNi`V5DP}FWYYI@vAc^94_<&$xqttL zU0F6ld-VBRai0Y~yzY8wJZx(|^r;Io^fRh{S9{guN`77i4q)PWAST6k;p*UYDs5{> zC7SZ(Q5jn7P6CdB4J0;K`y5cyaq)b}o{sMk724B*>#%)(aqJN}vnaePYuB*^T87S&KIrqY zx*R_B+zCp<1AT>Ggki_k7!dx>;&CPC^FrIA(<03UFMS3NW^EdO-V1 z&qKILwgXO7OMM%+9@s)x>@3^^&^HxnyT%Lw7qrE0J@9EdV`l*eeI>~08c*MA*O&qP z%BiV5turgriwl4D_jwLL3!GLk9DI|ru$?+9c>&g4kQdCzvHXq$zS`h^Fd?kCD$H`+ zn?djph{At1!ZjVph&SFsyYK`ds7=29L#}s2&^HF;GCX5lpksrZ9=>m+)L(&9R&!d% z7Fb(oHf~2elh*qK>J7P2iUB=Ple6f%I5@#pXM3U1x{|Ua=L((%nrw`MB0~DXU$HMFX$ejM`_tk&>KKn<`$o^kgwXgm?e>Cry09B9J zFL3>zG69Z!jAV3wJm)F||1xDdq>V@Sx$X-y-jDQO&c|BzfAe3?*th@k1K25^|C0W} zkLABy2V?7F`7bM=ieMRD!9V|Z|K)@KNB`wfE9pG@DF5Xi7=RzgfB8F>gJk3Eed!r}$6 zul|Vxa4Mk?;MyBEZ>q_AR`Z%pM;<@&Zt5Ls@_uCMeHD4~^)vE3rN=QbejI%Su%sUR z5(=a=iVymz@oC<6n41tUOyzft31RJ4S7|ZC9rj_gFunsA==~Fh>Nv{*E%kEK{r6#K z0PHdY+7jgP^SvhTTP824dFt`V4EIWtC%8rp!(BxTJoXvJG}6^!JN!*L^lI?njNQbi z8pqM$%|KNigmJ4KkJ0*u310Z;hFO#|OwYnFowWg|96ir7GBWftW(hhai9wr;VMc-N z-_gYiOyF^gKB5)ezs^UlL}8a|{5m7rTipK`G7w_X&Z_O)3poSs7khw>mdJ^C#)t7j zd}HRWnXPiD$w%=L8RzDA-O!qvx!o%zyYJH`06~eojc08FZ>EVBdBx;w7j15S*9|TB zx*n$4K(W>o(O%YgO}HTLnz>e%n|$qJNxF%(_*x&ED3+U<7U+y@=eUY@&1{w{+>{+% zRx=?*;%YhHP3-8hR;OlmrL3-9W5OOiPLy%48xwq0%39TX2-Xi5zMzCr5m-WBAqldP zv7KcIXmGI@l!1FSADxG!2hS#d&_z*Dc9?v?f%!`358;DrfEk}+>x}Hc7tySt&PWHp zjMksB`pp_}TOokNn{v!VseR2rxH4s}?8Oyo0Ues$!Y0uQj`rwCm&=u!GSnIBx?y>0 zX1Br81zw_ykVZLEQwCV9F*UPCtIKg-qSo3qbCFEY6tv%U!=ltoanTZ%50)FWce{uP z?|N_nCB&OUeB@` zJleOA5R}O6ZbRCA$*u>lVe8kriRhc}>>F9i*%xFw=6h;pCqGcysm8*gc<7wh<(FW6 zhx8pR?{}KsFVWultG;e9X@);lE6+8DjJ_5IvkkZwB6pBsH1IlDL@^c2g-abbmlhWA zmMHgWK(>AdLAkGbdy+5#hV;&BUdC83_gF+K!8isLIhW+oiZyQo&P93UvWzu<=WThS z=AhQ(@vj0#Oktl78ybU%nA$bt57oQAx~ZBGQ}Co*1(BiF?B$diEClyQj6Ftj6^KF0H{!&`#nvQL2Q}}+CmUhwahtIeMN(E7aCR%Se1kX* z$qA47Jc&ptmtv&os>1>^>z><)D29A!vv=z2 zfV_%g`}7!OV5h^tz(4+3pZ{&t^NYMVQ%8VyAp&K3H-_5 zivyyWvx{bE!l6BIrddhR0*CPP`57M}Q$lh-QnFV+Uqpz3ciKn7JG)vo{KiDc^NtF2 z#^|-%_~u-{eEyj1qm}T@Vh|q6%ITz{}_$ z8+dQ>!|Q!d1K}WPzK38?1p$x9kR2f6ki7UK z(&To2SjF0|`U!lLUm`RhRG+6P(vMj7+gml3-G@zY{#W_o8*To1^&e@^TyWaMdHfSd zRKJTd?|8j!<4bybJ?feE$j)-z}pQljbWVW>*K1VVE_JiHnf5){md z_`5oSE`HGADs{hAk)hY%hBUn{?x(vgeLl_q2|MR(wCX#zqpseSF{y=Khd3d0OH{g_ zxVZ{txxpc~|B%NW&g82$ASo12Hk{4`{Y_dc?8u5(?G)$;PJB^~d;y>Eg;UwF7DXLB z2qfQ|tK6LLeXarDCs`?1vter;A3u*_;);WHki|e#2Sm?GxfN-c!2++&DZI)5WK#!4 zc>>?N9iT%j6izlwQ6Tx7bSC2$)q{2upJ0k~$jt_d0>?c+g;#Fh)SgMeBa32k&o%=% z2I1hleBHNd6Ju&CwLpuUTh19Lcr8-EXLHPnuY<=00<|;Ta)&W5-l7y)LBEWikkYUH z(5B$1Sf|yrk52}7$U5_!=OXM8^9rz5%KdoGC0~9L@Y#(@zL~pITzWwKDOq7Ngr8YN z19x1+HPyXhU9U8e4wvKxvE+HT80!uEL$d8CCLC~dybZx=OLpVgwpz8hl|Tdif*TgsZ@7hJmh8Z9qJG2pq9yob zHJ^?uTCxF8DDZ+7_yvC3tQNPoc#A3>Es6S;sv_sREV15d<2k->Yq@nERO=L~b&2|Q zD90~#dEi`*XU8c6G0BIYF-s#!<&W5FRi44&Q5R!4+S0s|-Y$F@uC5L}POrZa?M<(* zwXGJ&qjlKo*-%q^32|+1%aCtl5d2J(@=(k%msh-U6FIDlh;HI{e|727wgD4){y3*GJ;Oa+Hjj(Tf92Hd<}&T_5sC2v$U3q6skFN;%gw2c}a@PWd__ z_P&k2dN1eC+yB_Rcd6CZ*zmRi1hm#Jg(#Dj&mHoQ8&O6J_(imSFQoLDk*kZhzP#$^ zmmzpB()_YLvjircNgr^yuj1|<#^sx^3ypu&9G+ToU~_m&5rP}6GD@b7nX3sm5(>F=`?ev!~T=MKyQrnt@VI!xsETBlmUCt4kuNBItAQOOa_luI;A~&Vw7X_5OoqAFJLA9kczfjAi*@Z$hn*s{uBr)p2e{ng`;tJz6uEp4eu#w|XV zAw}l0J;%|kHf->_s6HFjohGK%NElEh8^U}(@K3|Gq6S20 zc=gXjl2?C66YGaqGhM&1go2VIkWBzGTDzL_#lwMT{x@f#&}m{OXiAZAG9bee%;JAS zYap+&zA^mbM>+=0eg(in$e<)Pfkajy%N^3`NW=MB1ty4RyGaLw<*7&qQ-HLh^$q-k zh3E#i=i>;S>Dt5fY7CQixfp357;ey=qVm~>LR{P(VqSq8MblWk_TCLip_Je9Yhp6EH1cYrb1J|}%f~Lc z;k%TNOw5vx+o8S;uQTe4=gFh?;>pJYHm3DiAaz7=7!iK(6cxlIe`DQ-WXg$#{M#Yo zU~KXGmUrNur5@Y>t=BO2C}F>biVT_R!nNACic|0TR?VkdF2?m!KsYs@PBz@PAw3k4 zi8E2pXF{0BPNV-+XW(7jzX&zc@*K*dHF(X#Y%LjC90BJ^`&XEW~=p6UqF`cJVDqJSDA_F0hPrionLxA-Dndh+r>T z@-r63iqH&+be7dw;%~_3)B^(1T3p%68$xq zV}Xk<{zVbUI6fug%RO{i%V}8}uYqiT3Z#kve~mxa!y2&2me`Rc$w*_OzA;cYk?L@x zT!I_b@aa{zZT{7^*-$1PA<_XlFaD*WbK_?)^s>=UFI_-&nqClnoTeA2TosSEFvEN@ z`f{uELdkVWgV#Nc1Hyot@wICxdy#NI_#ZP0vD7Lv@m$;NX0*i%bI!7XDMczfT7tg{#ag$sgHhdytWqd= zpJ44eH{(CpkDQ!_0&TLO{PJ23tDk6WvwF-Q#4YW;lfIOqC9Swb0zM!2%9EC;-1R!g zp?7VZ3=d08PJ2?RVQa&kKvqUcYn3md<)xb1yArL`wh$7SXL9A6iV8^KF}+LCV{I#Q zpcadj&Z%bGdM`=5u|~%GJLR1!8`ip=-jUPkTkxwcZD4Beap<(q!033z>vM{))8b6+ z9mFLLTdft|XmN?k%BZY(EoZdnc`Y$=&_CMQ+7eTHe}G(kEXb@?^#6~^^a45s$%=(g^gfBh{ONA+wOfhj_7U{@xHYGbld}6L&F*8o_Q5*65%f{p zt^~6@D#dRQ<`4wdg-VQTo^Z!-OHTX$g@|1Y$s5B4y!yuQ_}4fF*6IE0xHQ3o1eQhR z-cBE$Nbr?jAKa+(f$VPHi)Rhx zPgip&tkZiey2*S80$*vzemxaZy+nP+fQoytkb(KCWIena$-N)(KeH^cSuuku_S$)7u_KDm+T7K^0X?9K@Z~SN0ICkLGN9&ueB%WBO zHxGRz>KEa%;)z%cZEMlX-P5)`1Is0Ir(;YW{)u*ji-u6e*59Oh06B{`e0JEyG9E#h zrICB#3Tu(ej)!<4emw`ov$H`wIUB@JDu}Gp%TKXqe5a)0N)V9JFdvMI4;|K@X=~ts zxtwK|9lT&xQZMi+dP?1=N$0C*&S~N=tPT~w-##7!`UwL(Zudcs?eI4yM;Tgo7e2@V zh?-=FZ;mMk&it8+|I1LvPe)hQWZ^%GS0DbTUqSq{PVZv4AZj~xSp*|g>sn)E85yqg zr*8X~=Cr>zmeu|MUVZJqIg{bySUIeq*fyN_krebj3o ztkb)ZF&G{{H&G?7kt=e$8Siy-NlrJXXLoaab~lG=H>}fpDY|LXEm^K}iH)j-7v236 zE_$knZ|csU(^>%Xh0DZGzC8~s7IC8yn!$ZW_(h-vNr&WX07gKrCgJ|Cor<6eZPF#; zXtO&H7v}(fTQqAPYVqouhcADX^T0a2_X8%Q|KdXzMN9renGIVidhHq{)G4M{-tlCX z;$4rrU4AjA%V2hwf4exV%m4lgyJVf-6VPRCx3^6GRb^~unXLEPkL0w!1`YZ|U{iMc zcWe8s)4LUVe}+AvA>Qp36&&-8x3sTkx8@`n5`L;6LXp>0WZ|`LV3#s^=O6fqY(xX zaVG>pL=ENoH{8HXzMJ&0n?6C)9sP~E`w@SJveSDEibFO}+xawYtv&B0^_nv8J~KqL zE;`9vTozvhO%R2N5nG=i7>g2H`Kqo~_@PwreeoEi;7TT=b}olP8a3tB@GxagWEog9 zrp)zPMz3y8Y|i%t=vbD4uiuoZW*Ns>0#ry>IFEER#`K%mQ~+-xhY{~rWf(hdP=LCOAZFl(BFVf0Ip9 z@SE7k-$30Vpm>LmvJxUM*-(Nq%XnO=ZDax~NkM-6_C z5^glkl6)DZd0^2kw3LU{O!;>y4zVliS|Ye(9r)5Z@c}v@TA|J#V7ka#sy*?bO4bMa zj6MI?j6I*||LUm5d}O8B%MQtx0VVdjX;Xg@gNKu~U&)=98X)a%dxoF(dk zzoi?`+}xn=WnE3Js9M=7f4P+Q^fRg`z^7zwP}h>xV*ae7*uaeq9k2?4l)}WO>!tB} zN*+s0i5~N(TMMp|pQj5hkSkHp1m;--kP{kR;+whvdLA)p$3NtEcbNE|$%yaiXE5j= z)z>q?u`$lay(t0)enI^_d)~mD_X`)PnT1z8woRWwRJv0FeEMf2?Vt4Ezj{p${H@?Gb#eKkvb^y! z25WNGPOrLWGx1y+k6%5543QH*Y3>6=d}ZaA(IH?$3{#;@!%M+dB6yT|i`opna9U!7 zzc=%_ToXfqu$U6r3EK+y7^LYjBsc#jM2YooHWD`bf+f=Pv(n#RXq5iE5E=Go0yXdv z+Y&ur=j(894F>4*_hpA>D8f8^0v!`J<>0>(tgP4i3nsrZ4CUb$up;U@RP1p1I7ukzS@jH`E|**|rmU?iQZjTQ0aG zH6V>%&4vD&=?m+>iEPw_f9*S&nu$&2!UH>88?@WSi}2vDpT6DxEYtIf8oAhCzgoB- zG79~)gx@$XeZ`HD$1i2(cf{mA)Qzk7cwOIF_IQ2db$xtr8PM;RkEJLipYA}e+;?Sq z-D+V%_QZQcZTkP;{q;YP>0ck&KOb`XH{zKa1yA>||B1f-nXte9PkBBqe@2c!uq-`( zePsW9NcW%V+2G>oLH2*&6`AofVW0g|-pnrNy2`i_`OA=!PnMK4vV^}Lf0)u-o!~3t zEN9Ncy7B*dIrR#xb+u)a5)6gzGUig@=Svm*dV6pIA$G==BHw z+61?-3a4^e?>$z_&%MX%WePk-T3~@3&qr<0n`pO1x4nnzcAkgJjDZvlQ;Fuoa9g;gASewZk(4sUuhKPGebkR3>)JTse42kGEw zTUB9HUi+JmUtaLHU;c60Kk%d4zdg5o%=dc#eAkW;8OcbCVdoYqE6Hzi?huoRM47g8 z&n<{t?6Ko5fF7Hzc5x#D85vqy)UcX^uaq+@IU;<3r6WxX9f7)wF=T`#n@#g;cThu@ zgXXj8b+)w*UsIv_5FLRS zpeTA!#XFP5jfi-%t3$BOk&cV=dh4;ExaUZ5vp&Ce{RTAtgQ0oiYi1P_=Hb*B*PH+w zUyZ-`4)y9r-iqwzpJK2A)d1HtRV9?-O`sKz?SQY5Qzjo^H?vp$ny42$+kEvA8b5f0 zXqwlEUEwik{AvDFM7odMx#u;4;(q)5xE=T!GH@LW&Dn`&Th5Ax=K@3|gq;}^^UzC+ ze2+AqH6K9xrq8)(-vVsVmzt>G62P~-(>N(^1XHAEpjBsJ8H~atzOiGi!iF+1UEt2Z z2AzQ$HFt&4M7PMrpWzHFx4DD5j7VCBUI554oShjt1MMScAcy;meA4?f2MlUeJ1)76 zFhSu&;;>6_xS4c732sOUj`90}x@nBx4^>2l=ivhs zUv)OV`qI~?74!RsrnY7losseywj0JZEdQV+&5@U8ebUuVPEO0yob?NJ?=921ZIv+n z)2$eJD;fS9)n0J<1{jbF5%uKZ7O(vvnrtj)FHola6I#>yK%(D^xAyHcM>-6;JLEAm zuUq+bV|w2Nn6<6=k;UIvO>%@Z*F~sXsBqM0KUdi|?0qC1c=%0g!zM?i#>(HC7N>%7{Yel{gbI z%>)}5mC3++PX^u*!u+99SO1%4kJm@)e|&I>Otujq!9)b2PY01Mjkw>;?X!gm*}aZN zZ_n+o|H*FumOWk{**_oL{$r^z#WY43AT#pm=`unz_L2-lOxQO>1|RS251z9#@aQAq z;X?+Vk~BOco}QjUc;>_M^f1JP{la798wOWunoUbO-bv331P5gOqadGl+53=EkzX)j zJm6scIxcPm=am9H>C;II`^kr?3VDZp*ccD?bjk-vM`QOfTaWdK`k8*oK5~!mP@geN zS4dv|NA^|qo<0P9A-c&YPtG1eVhE&0taM@l_N8>cKH42i|#FxnWvGty_6aEmO)s6Gm;UF zQ?1iDt{w6PxJQ!K21=0)?9Pt2+EoY(>S&wMSjL3DMbsUaPtAB;ctm3od_e~aR>vq`=)h}tau99CbQz%+*L2oButC*fERERKV$9Z0^EHvoXiT2J`j* zCO>Ti3O<^j_P{;)G5Bf6sQmQWe)#Di#H)iT_QOvLwd;}m#DHv%pUylb!%x>^-SY9% zOuXhGeFQ%N{|hqwF#7kGyUCmbneiFn&@H=^J9^0JJVnx@=QVKanaFuF7-ZQ~UkXV9 zxgzp4?tvqsj#navWZem<@sbbHUvVa~7)x~#kDqzp&}5h2o2k;|@H_KQH~IUwKl?=0 zj(yvom%q&dYMP=CfB$a#GKqpE(?9J;KmMYluLo3+`K4(&AHH_AA6v8RM~LWL`*Dd8 z2t(kck@n*>V?V<0kIVVeRwVr-?bu}ixza{FXD%OGU>hYP>nN1hajI~9EE!MRh+Iyv zdD(+V*ktft%IFwwuYv=m71sv#&dei0(RB%#O&d|azJ|-5u}(@wK5axq;$bq;_*yo; zG_tla@gMK*84tc@*UqGX3O0^`w+pcA8j8J zXtfVpUHcFTo_*LVKT$>3k8jA?ho-n_rLD#x=sNZ}T`b+1Q2Q_o!&vfw;aP~`ge8u9 z3FLL0HJ}w9X~tK3hy-JW?X?yTk zzdg7TM4_`ldk}s?SczqQ6VxUwr%m{RN%E^*X^U_)cox)tOnCNTpN9PKWb9Lg<)5@q z&*4Pp*r$rWL82luh>NT$Vxjtr_{N(t2km^PurW3}C+G z24w)YCSi)fdkedr%4i@taHYEu;PS`7_U(y zM*4ey&dhiByLl+(!TbO7(&oD}XJ*cvIdkUBIcH|d%(g}OBXi1#yTghk+hn@n=Z~jS zgEwr35eo3d{ki}~(ZlT1VL$)JgU06X9KC*b?8~LsX4-yH^y(I}J4>$-2-=uzL!cFH z=^{}?Pw9t$wGBYYzqI~SI;b*f%m%%UCG5qzT;irxd@9($M zB3ey|OkE~**<|+^raYzm>+RdO&)|YEhCDM;mq}l?3vANLi`|XGW}=@lr-sza_tw)k z4K-D|RBgC!K@ByWOAXCU>59wGE#~o5gw~i5IB(cBV_o*6HOuaOrLi1`yTUxX zpms(B0R+JQy^fyO4_D2uS>P@_QG5adBbGIAf`~G#L9uJvOrCI-blA_LVfXDhQ9C@E z$1TfLce_=WoY9HlVAxXrMz}xLdt&XKC zEN zlg8j9S}x`0{y~x8l{b4=CEsi|(hNk6d-HPp<|h473SA)6!BpI&C^ zY0m9Hwi%Bohpor0%s4tG35^42c!uP5CBr+TQx`afD?pHQW{IN@L#Merj}fjE(aj)w zUE1!Z#wnr~l=o&4Ba`TV*kRDkp?c^sqcgj?uxsH<#xBKSDwqGdPtSN|u>_a(@3KXb zXwTCg4MQhepN8BYNidv;74I-?tGe#H$3}VC3}F#r$ZfEihG%qV?*p5T z39u>6XYKP6kPUk3Q7!wz0fCK4>w2o`}F@Z(FoEXZY`u70p-QsIx;edo%~@>J#0!)~>&&dRUq zFFJzIxM0!+yStCVW-QEKo#oS6G#C+Vemy*QQ#U7B{h3FFaD7kn$CDM@wNAPk#_LA_ zCCc782&n!$1VYZ7MBQZ7(*!wtvis_@wISKRf^0(JCNINZM@S294E2Lc2N~0C%bT_> zJ7AZJ%c})(bp%m(73mevRa9KQr_!&C(yjfT?4^krmw-agW3zdk&$)lLR8~~U+}V05 zEU&uj_B1@WG_mJaL!*T8ozoeMd4_KCW*=4e4}KjpC-KQ6Z~^GeU-U^~%Ifj8!q5JjiZdxxZsMq zU#?;acY);Gv20w%?5`seY~iag=Xv;x`R~lJ(K5!5><8w@`DZ+Pb2kSEIfWV2kq_wC zyu^hM)MgvIg^-4}}dRgsZyUZ$(-2CRl2JWrU_%M%frS$`{&_KGHl;O8^VI z1-2P-jk6XcH$OG$Gii+4ePmo&yM@F6NqN+RgzD9*sW&%2k~GP z7*k8qgQJ+bmKC4dby%sGX*_Z_lC8PBwPtytCw8Y2_`;7jm-un{fL5JxM4H8pMmjF5 z`wFHA%0=~OzY08Fi>7OWAqjt-i7Yz~SmQZzm3uwAsaAVYSwWKLfV$?0e?Pgko;@4} zKrIf}F&yETTbZ0py1i-en9M-aA-Y(W0f8rz?y$d62>(F+O7|qX?}Drkas3*`gu-S4 zT*cA}LW&Mo6dw$t6rAKmLw*{?Zzdt3ch_Xf^_gO64t zU81lbKh3v@j!^yCds&BY;w}h5na`2Q@Yi6!?qqo+MsPaKZe=bKFL|Qo;_bS4QE_p+ ze;^$ek8Z8|JbD)5*@QX{Puqoxz_-~#bephPe}o8pThk}A^|#><+G_U$>fW7Ota*BH zCza5Hllh|uhdS)iGY)j!PV2Y0TYT;z%FT56=a?>iQ&Ny1Pp=VgfL-Gni$Y!_qU>YXtpPhbVcY56LWR0!Sn$C2vwCgcF8;l>!jJkf5`y+eQEu5|7Kau|iBmWHna5aF(WNv7B zcQ$ha9B75t{jVQ{)!D|?aAQb6$|WTGJ6#j|Z9iRCpVrof9bmgV7V0ht)AV^bzHpPc z;3(>DX}^a4*;O8J1KlDfnLY*B)BZ_I^@A9LG%kql@Oc67o-n4QaTuYanzxU^YH zgTL>_eFAR^V`2v<-v4^tK7j;`yn7zhJ&laI*3x6top}AHa{~;Fx-XFwt~WIE-$-3U z`m$rum(2z_l1*G6ZC1GVj6Evbq9Il|JE6{5mL@2NglCo4`&qv!-0e#?xEp>MG6uHH zNvR<+w#-V~7mbGi<)^Xz z#L;612R1Uru2c5m4>L#2K1^aPzNphQm{@$#(n~H#yIyA7SljSxO^wow!8T0Q_J~lA z`y}4A)=Y;?Ssg~1#*VlhxU<|2+!@({J7ovfog*(`2X2=zRORie{M!2VxE)xJwK1uP z2uiqb9HzOX3z^tPqp5+Vns|y*emvoq*tPb=2yt0~*?>0^?om;f*?Qmuf6sFl)DwUI z?SYRX!(RU&F+v&eXCs4avh$cz6(gjCbld5>Ria6Bx~C4Jb`iQrQ^>a#ZNSJUTdkMn zOyonUqDXD%=SESo%e~dYF5({6O|6aHLHJn1-rn17_TDl|j+!xJ?Y%EiUwib>a((R= zOLnZUF$OPBUptou$LMQU47xcB$eC}h) zjbRt`wWDI#ZIr(+($|FDc>3Be-$?6&QivYlt4v?pNW#SW+JhhfmENO2MSbmSKJj=V zx3l`%x$Hz1Osua>I$m@|UprL2!3H>yzP20a!ceGRN4a;f7*D9LZGFR7eQm_~K^U#C zoi3fX)BOTcj?&kz-MchRA4ddweQhOmzZiY(^a%b%=xgoFoFFo#uieGZozvIm>ZU@| z*V^4T*6z0JJLqdw>_@$=<1JFTrtwqE*_Gw#DtG@!Og1WG4>C%c*_+r76!4t3 zyI)e5j||{3maG=avN)G*e~@MtTL3ccqck(GWSBj8Ch<9b_n32a=p+QbuvO@BY}X_@ zy50S1%={EF`$FXJ-myM%;DZuwJJ3h2?G(Vv&_})rayzY$%qK!++b^OqYL) zTmt^_v63#2xp5f9&-SgmOM=TwBez6hYvD&_`v#jY6W9x9GEXPA7k=eu#^*1^UWljp z1?+`Hpzp|D_$tF}0(&8`8Knb!W&0nji$=2rGHH&c*)g{NnHKGTKybj^N`qmeIp~%l zKH`^Zhh5R;0^#ebufbh&zp)eM&*HAg6?a8$yj@XD{_Lbb<%jSwy_(p*8RGS_l5k-^ zbbNe2G-VuPWPOfk6wIOKU*X&PS8_Y_ugu5A;r%Q2g?~kV1Fv3?#J^JgIurr?EAxCh z+gdCR9FEPE`&V+2f5kT({3|)vj#e1_D>?J8s2=%Oa@l?LIe~wLek3{i@)G@kOx87yT*k}ubVv?@Z0cG)fkku@Znk9M37NjPMJJVJwYDm^Z!I1WEYQ>2Zo2q14E-E51vQ8*jag?qUG}7mMJB9uz{Lh zggp4(t9D)W*c-a=ajTE8&h+QcJ18MCqK=> zRYk4IQjT&b?qMhsX4$!A7E?@p>6CwcwfC>jp5iVc5n~1Wl@BSK^AMJRH2xa_WpuRD z{cBg%J4m`|W2FlvCN-tmLSo0-GWXi4mi=Vtp{!FSlepI8m^n1WKfIX3Q)BXw zbT;H?Pm!aF{qTLY=A*48$UK}^lX}}_9!I%ECN&+x;S@n$4HI&wPp0d__S&}jle-~P zml#oG`nWLa3}g!QiQ*UkXkx}J>BarD*C#d6N8GCs!NtA^!p4vIE1U*IChZ{J^Y#0@ z-1WKgA5o;*PR4uA6tX+LJ~QelJJC2r9BTcWuJccb0qL{+l{s-GGe;`3A_7_$U<|ig zjj{f_Yp=GBx~Dp2`ZQa1&VBDe6Cj+wK`_}3>{NG7NK}329qj8HH9dlS*h%>(oV@(w zhU{nxSqk!Rmlu|Qc=&?+ldli?X9<#jNDuL%`xhqKe}nuxBQF1H#*yzj+^O|vg0|mc zvX@&buAOR@6Nf{?UK=vM-hli1uVg*iDqqP~6VB~gitPNvQI0G6L@QfnMCv3=veP|-dMLm3Y zg8jH?>u&g-6)az@y}XOd!#ixs;b7q0p1*hKizXO~G3C*CAv+I(^Qb!(|9qxdMayJP z30{nN{7)%TrZJTA-R9Btb$jR9==#v_R+Z-0xaaSfK5m~AiVkWshEH)7KE)M+69!af$* zNDSRpG}-3+aE%XW`<-!@5u&qIVU6!%sipxU0|Pr+T*BTyn5xTt_O%i_G5@cQZx+3l z1Pj*p7QV>-8WgG;2XPIXhTkKlrw5j5wOG`;#@uC!XVu+yudxoX*DHotgk@Z$w*SI- z=sp&|Vt=v6NE#h9C*S7JnEfM)0vudb`NI20@qaWw*CP7L#(YfssNKQT9^uD$?)tNs zzWYkW`(7j^+2Vcei~XnmhJoSA(cRrAt8KWxy4a^1W50-a-wHZg7VoQiLcFg&C)j`b zcwcO+uSmS_9%qe>_cc5$-q+BG_MbiOU9zoUk0LxdW{(;_-d9DV{ih;;PjgfK62YA5 zaS0Q|W9(7o@xFx9TD)(qduuXGjIr^)57uf@bZaf{)>=#~Zt2Q}or(7i@;74G@)0!s6#i+~Iv6hfB$|`#uN;=e`f3@+p1_EbcvD{w$SN zIEB#^em>4!9|1qakUK~u9Y^2eeNFfKKT8!OE`R=kYz9yw^?iwA!|FkP8xleX$SZXb zPG(zOrsk8Uqq?vJrQC&G043e<Y)x5lc1Xc0DiD_B>`n3efSCo8tlN43JAAbY}E; z59r*l04#jb??Q$oG~HkROGUMR8@+#>Fy46Z&LDorjW_-vk@GJx-WX5D3-}LGJN6&^ z+Au?o;t`lA-dF~GZ7%1e>A!!E?z1NC%J#6)c-rX{-rF7x5#_V~pZi-;kaH7h9Iq%s z(Yc8WShCa%7di93gHeSgYs6x-qjUwJj=)x@xf$z>Y|%LU8~FK0Z zkH~3(ws3Tr$E~*yS!d{NP7Ab>#cK`j>$?Tk)h(2qz%$Rx2u>`see2xEK3I*K z+Y`nO@^{Is-8fL!ICR<3`e|RRpZXiEpYrFN;HCOkFY)Pq{oHwf z&fvc|MFxLkb@Bcj)f4Qu`kY|>d}aMPKR<1({nqd>`>ml7t)Dq}JQ(k+{Z>Vz_0#)v zw(erg2TSMN5c^Bh?jnBTi75DKB7e?bD@O%Ij`^M>{0hT#STmCc9O%pCS5LNNS-%06o3t1-%_rkcwpc(o$ zp}HK+N0ZAOYKY5aX770C*$%CKVgJm(^?ZrfzmZbz%Sh^&Y>|R3`9bTZ-Uk6BDYOp{ zjA!Sr8fi`3t%9$b1bbPC_lP@-N=gSZ zh*TM>YaDJmP-`pheucLUsFl1DCK)^0e3x5 zcQ|Dt2=XVg58*(lYC0J9=kR5fO#I<%*rAArc%;M;?S(|4Ykg(3BuDjWLfMV5`AV$) z{e8JF|E**0Cyt>vd3>*#B-g{n(hs8U{A{_-^K+81bU9{e%YwFtF*0(&qaDpI-DpjF zJ1wu5X=`KK7?X!j7DmhKcMrb8^7`?AJztd9`%w9W^7?xKj+WPt{A9GeK3p4`PIo&o z%>O=l{RwW!k`DL(*?GW{y#5oc{F3DLhcsP-y#5xIjF#7r|2yRMN(7FV*Y<_H*5A0i zKKyx;B41tR(_gH--pU!VGI_0fg1pw}|B1Z*(Y&$p+VC)WZD^F_^_#(XXZ1l9Etl8b zUg#nzb8eehf9KpZ?GR; z$AEc$w=eizf8+dq!aqH~ukz`h-+N?U+o}5kWoUV0f7Q(9nqZy~kanVpzTK@OzItikimZ_n7^#CmzrC z*S`dQAIE-(2er(8*x23L_+su0*g5~$Wf2C&c(SAn5yLW6?A-lC4cL2Llz(h0+7rr^ z=s-v>TE!6e6P>=Q=u3+9`!e-@cFL~87;#UreL+bXXMGX8oKyH$P&ovHtJ`l5xZXsg zP3T{`m1fDQX(ce$s<}@mH;ej~6_WPGelL?E{zGbyp;mUHst7Mj&WKwJQrJer)zU?& zpq}{uitr=ZSzOd4W6EgzqEsBW@_%IZN|a|(MO2=)?vmHmP>R(M54NWgG_KdN@LKdRRKcrZ+x@%>RJ{BCFc zQMKdvqi9&NF7A)|jCJV6`J=FG$M_&NK2nUw3}7iAqc%J5@${#Nzo$F4vZDZ0-uA;V z$m(yBJ7`lO<(m1i*-b(eYHHNF%lJM1dojV^kex?x8(Zm9r@8&kF7_e9kLox7@AIRa zmnHrz+56t93l_%M`^2|N_hq6hMoj?fZyuP?e)^gJ4h%KQe)^%Izy~kaetPkA9=*iRQ2_T$=5OZ3`98{6^d)qG{5VriXZ*WP$SAfRwUkd0(3>*k~`-Gd+Z z&#tK~)D~)#i0sCIZXh))S{o9aI+Ca{`r>J2f5$b6^J;igoP}_t`kpy8T!!;@3RT~u z3&1V2?vbVYv8U5uotmthm(*p9wvCe+**13U=L+vA)Tu!>yB>&pwfwI{-Mqw7?t-^p zyVqIqA?*THe2Bkn2Zv&Pm4uA=izX$sC4ldrQ={&Bz;W`q?W%PS4iFRS4QbuRv{a|S z@1F%V4k0~U#1s*QOUV)|xVMHJ2qs5^`vUiUg(mFQFk#~Vi?ugz+642>&qw#yZlej<0IVA+_a%$$=>{1xrAQ}gv1?s3si+NH_|w|BzPV}r_9c7q zZ^e?s__uP&oWchM{~CZO$bCgrsDwMHfP}QGA)#=*lAcQ%%tm*;&r7*^U|o2f@~(-J zexLK@f8l}Cu7`wv9-~B`+@_I^+zu3KWsWUyKP8U^&N~tb@89S?M!KD=G?xed4Qwf{ zu)ng-(6nr?47m=|D#!D;WO`LIPd0GPlDI`2fFp7%_c_>key#-=`l0x(<4p*F;U~vU^<|AvYM|v4X7;k>QlCKO*!7tCnuVN#cIO zkE+4er5&;b-5qjzl=HQaL!3rOU1s=d95J1|e|Yuo{WpP6|7V1EV~4Cnb5-l*R#pWs zQo+o&s{1*3Ly%ovW+R5o`k~hPb%k9ppSL!y%VyTKa;2(5H*iI8qr+ffj@mz>SjTj$ zqepe1Z^r7lJ=Af#4u|RjSFY}(4vun-^#9VPK(BmO0}*8#iNCZP-J)B%WqID{l914L zBNnrPBt}eS-Kuv&>b0_TDOaB_lQ>UncT`q=0J9S+pv4*uVLixNqB(m==u0#>5w3H zkNr)%JMHgA_jF;W=Hn-SKHhwMK&ro=kM9Q{%*Vfw`hxTEGXQ~kX+FN%w-BF?7kHSB zt}<%97OeezeAY);rd%{1-{FCGI3NG&BuL1&Q8w9r~6f_=3_5kFKs@4rC7&JR>!|_J~GI$ z`5598;G!o?=B1tFFgqRhu!%XM2?$*#tm385w=dY9blmxN;h6d6?SYui5p-?d`&-(u zn0(;;B6Vp8HQ@FjOv84OTyAOia}Ky+7~QWEShE#>tQ*Qw=3Q^&+RrvK#t*o=uut^o zC0VJhAz@0=K;435b=#_9qK;i~yY2O-;VWOh4R%v7n}6H}=Q?Cj^=ZBctCg1GC>iSW zMNhvzp|Y8%EcbA7V3M+Mi>?`=EI~utRCZgbEKliDymdjMaGdDi(VK+m8gN(r9uWan z+Mf=fwV`h9!zP#>#?n%jHg@+})R&_8w7zGkExx53L*H*BB1X~oCQH&|tgk425Bl9p zr|<8d3T0n5eShBnO3+uzVQ??D;Z`h>IIbTi9^rDyQ4tVEfAsAkahH5BNo~GPVgrm_ z!7funY2lV=NqyxU7RwpV^Ew7X9kUXpI*usJ)M;Q3xtoXlN(>U0&Y$~omj@)` zEn0ig`d%%kKkNIh_P563>0goc{T>!4MZJu(zF&w6I(mJN@OdKO^P7Or!}|M5=o@d? z0X~n6#>elcwLxjVdU;~|61Hb4@e}WmU)VmgDwB*4VTqsg`V3{nGVX0e#b|?7+84(5 zC%mZO<)`u2fa}MSM<^VzQ}520!!*AL?n{Q;pBHl*qFh{^Ay?1be9Hq2a{p-r05in^ zT8lMQM*!^bq#CB(FX%lVHLimXlcq2q?_pC!cC;bvXx0(UgtS^aF60bb4#H0}p~f9t zmK^lF8Wq?h7_T|>wAL03#C-HlJ0BQfdb zZ#DukAGNTILBF*BRTQ3r?0L^RDw~eV{>Ix)bi=jHzr_}B=I=zVjdr`a{3JZXeN(2n zh3HBwbbX7u-5tkra4yr`SD{W;f9e-PB9qI{N(In2MWCH-g@JZPpkEPaeJ(#c5kMzJ zpzZFx2HNgHFTaX?N`6i{fIWtCVvTQfGYxEG06X0pP6n_I5!iaSn}MwlU~jTUYXVqX z1a`Z7>KJw9_5ila{h4o6783khac$!_RyF>!Nk!na64w-TIWRD@6ZTWkYxJd^PxDiWB6N)sZz@73 z?Wdq`($@f&mi?1^&!)9m)aww}mErn#zlLnyG*2MyRtu!vS~!f0H?my+L0!0Yt7d$pUP%xThqMz_qM_mPnxEhvdldwP>a32apaL_ zwAcJFby3R}g1)wI_YVWw<}BKu#rZjxuMA^KMH@gJF)hU0oS$G}Q#tVSa?zCQxH z-5qFP!ZR`KZV<88%@t9AE5nl_@OWu@Knco!-@jMHZd!6hZMV`F@3Y3BNSHfG> z_tgK6YPs9Nboxo~s7`%6(vPjE|6Ah1#`G4ViXtvdSC~AlQT$K-*}g^Cn9NS8MMSsZ z`@KR{b=%L3czPO+r6b`kM|@~4@vqA*=2vlr&>Ja;aszv}2eT*T2Hk7}%S{dJeW~Y( z-pnxVVxF_gtXQotX7v!jpK`mZWLT*#KN=!Lcsz^UqKJne`$*t|v8au`;%)R#r{ApX z`B@Q@{|O?Bd(jR};ky)j?*M6LuodrMupNk2x}tql_-AaP`Fn#7cqQXDAWu)o=^p(o zE1x?~|N3Y0lI{d*B+@_W&HzpS47?ps_yg&PJrJJ#<&e-J#ws^2@%U!g)kjw4 zPE9_(Ill$E_wvmvp@uu}_u)>BeAZ8s6vMVhP*)`|2$6(3c&Vjn8z`&#+Oa#F+~ZLnfN? zb6EbYsjT|^%+HycKeL8JukGX)V&epcxtYwLb#?@EcK*x-5zK=8!nsjBbMt2*1*j(l zf1Wun0-2Xzcw7W>T>h-usG8dRnT#t2fuuBV z&RQ6OEX|hAU?P9!Q4!2h`GvD0m|6L=Pzij;)A=*;tS5Ei z2Qij%Km3D@X)X}Hj-T#RpETlf68#)^s1p8KOt{GHuY~iKMG#lIBnh;XU!jqs`P`}- z^iiM7waWUgtpB;iXXTd}jIsV9pi&fm0#1l}6e zs}+a_JL=9+sqna^tLJXxY^Qs=&Fs4L$tKHxJq?0I{_yf^B){wysv@~;%7pm{OXruV zsd4iCd!-lP@Pj^Ax@VXv4Xh4RriG-7+;2uFo#Q%6Nrbms!MjE$UF5zrI_VsjEhUMh zYVpd^Nf){EM<<=*PAeusBsUG;w$0obj3k7dEW#+EdGj=PGN7VQ@%_e+#p9pGyWedpzQY~D#)QqE)~&Wo2X$_8zhPMJ+*+Crw>^%4=UfE?tB6V* zM~NEuXY6qXJQLtr_Y^<-?^Xruh3uw{lzT`ZYGa;t;U`fERbS)Q>!*Ny7jETeVTpn3 z&Bc^k9S2XliYm2k zhJL~uH5IFWdh+aw%6YRZ=J5Y!{=b?3kMMuL(v+(cXW!1|_AhL14_7zwxehhJAkH1aE}_)TtliSk z9WL%()%cgf583hj1>-iFOIopPd)qD`GxCUIfch^J;`Qk*+Af5>XxyR%{>ulXRJ68T zDaaQ6%UZRuA!`ZEn`gQt2Ab@R%J6bOWK45^+DeA~LQPe>T|t)9<9#}_W35V^UgkBM|Sw!kL>W7+S0OwE=$bnr4xON zU$3>VAiabBbvo{A+}2v+-Gxs`)gQ9sw;$jeHn%EDCwyT^&)D2)P$g&gR*VV|P>-Mt zxf$$QtfJRZSYCSFh^#qtsn2k3H!=!$MQ3^2>estB9%hp~>E3)VL+BTlASA;2>XtB9 z;HDAxKAhW*i|*`~7NZ|B7hz6{X<-JQc(^Z>)}t|(Gu*m~z))RYbxd|o`_$!C`UnQe z2578dFa7(2_2jzGu}A>|8Mkj#Lit)0DFp#vDNMrl4jkWp(PZe6k<;8BMRZL8j^HD; zBKn<48FgjjOuFCnsf)IQDGP4&{Z&q)r5#R!0+io)I0F`GDg0*t7w|64Ze13`Zh4q_ ziOub@gIP8;PR>-{!^g{R^9K( z5mN^02af!O`_|q(f*27pph*AWhrPEHiY|s?OHG&~m}h3qsjk@4ax@9I z0*>TlAh=NV{c~*xZNwW`-ZY@h>d(ljxuxZ(P?}_wZaRMPZ2q|4epLPAQ6l9d$O+j< zEm$mwtbcdI<*d?l_C`V6zd~6R1V%wVx3;WsecCUOR@DM`&WS=M6{=}#tEIS`@iSvn zFskqsp5}7ClC~BB7(;zs_QW=Iw;ArYkH8|KmV>DUZYUgEI66YPt?fAA8{9K9K*8*kL8RWo-kkERT`hM^L1O8uZyyK+Nb8LJ|>*6 z@wq$E_Yc}Nr;kUfL~~jRah&7w!2r?N_i&~$BExl*tOXrlDtzM~U@ggwmwN{n0OTZtCfbo=9uhh&e0^54l z>kcmg&y9ff3dxlMbV7mV&&uQ4_RYUG0;0wx?U(_AT-Iia( zm5aq(mtTZ~dTUe`;I7zDfQMo~0p@nbZ4ofJJ+YtU=H%ISk3X3^zl)cvc(XzGHs&)! zIrOAO?fFc*|2>#He;~hTQ$DjP%0Hj{jrq(*|2x#tlV7v}WyPm;=h&(*T8|zR)sdl& zb*MN|{`utJp3mIwe|LF2sN=SL<~F72GPrI?se6~=3Iz1j{`~^1CAK0rxF50`kkmAl z!5g89+-v&7DEMo41|BVOx@irWY5vbt|3^0^l2_~h)c8MX|0m`DB>5v%VIRZZVo0Wy zwnzbgu$7@-W_g4_@yr83vi<;sjQw-8Yzs=Z{8_RC>PIabJB0j3WAwPGyy2e^go%~v@KCw_zPeVR&t^G*4g|ZZmuf9nB zd;5y?9baXoQKT_t7h$Q^bT9{VPS#hvd#HH341(nq7wcpFA#y_ow<*hQHL_n=yv|+@ zvQaMP=d+jBs;5D*DwX&6ger8MK`BACRLUq8OQNF6aWpjQ+o60ubprW3lb%L$c!XvM zLog|QEjy%qVs+^Z?^RwJZ!Uae9BEwSXK+OpkGP9jvrBH6vYApGU+(+iy$XrKFaJ`y zL=MK(3Ajwo)Sg^(Q?9CMK@eS}>uxZ1iapIuJylI_!+K|UcLQ&DGparC0w*j}b3Ao;oQm0qn)<>s$WnQ_y&o{Zg@-o#3hvAkA}1|y^q zyKU~i#7jfSRfW&>FJ*-NgRV(;cscGG;TPh^QzqcY!*{@sj4RXM2Ac>y_Q$IV_Z4ne zKvi54$M|ap`pQdcf7**|e`etCpL9<+ewR-$emo*B{*H}ba@_GtPBeaGX#9LNv5~u} z|El81b-V9@jq<>{88tN^RtKbA+aLdjEru^HoX_gpXqX6;Ppk= zQ0qq*DT&pE9~8bE&CvXCaYiJ(KlbQA&yP-w&q)*DBVUV`7kNTPGd(%p;`NyHE$Vc8 zc|7_uo%t!N3qLD-JHnx{ghTm`*waVC>#2t(B+mQ^kU1hkh9wf2wW1e?ko2qWfD)6= zU3IvT1}P?#ep2{agwlO~kH`|)0>XUL=8?{Mos#`hgL^L{ZBNKYUOhiIV(^cZ!E?3q z4&b?g5`VY}>}OeNClE;Qn4r(E&o1q`@NcQArQLKMmAcp6{AM~L$&||{zM#qcP+>#V z$v&MH%Op!aW~28d7T-3IpM^vl$el8kNZGv9jDg&|DUbK(7wM93#nmSBi?+FAsUF1= zr&axcc}@p%r%nMD@0BmD5?fJBLy2COv=Y7fg@{HfX5ppcnpp9)ilCmd>99t6+^^oG zMtbC@Q_TX-olC%c4Km-~tp>GF7Ss1~%QT45Gm6;^@He5NxL=x`si z0v!=rYAMHAReI%1*QkW_;!t9fJHbk9im(!F?i7?RI+eE4)`(PPxrV@MgG*VF4S`xB zKeA*0>g>8S!(;-pm>++qdWjcX5E_?RU~|@b2%hds_a4xHbvvo0U>}$_M=x z;?L|$N;c$}!Mv*J_)=($o<7D#rO=qFCbUY6qHzD5Axs9_c*Q%jI$OUwUzwAlw>p17 z;TMJPdL1Yx5{y6P-*un+lNly^-Tp(EF~ABX(zA8Wy^WL3u)dj`p5so1(t>a0ef;Lc z{EZn6`Vu!94UV*LM#q?J$mr&|j_@l0(Z&U+fly#(z9NU2-9{)^KcuAren`?Qt@4AI zpIHTpA_aVw4=9}I3_n-{hl1^(|K7?s!6ebBt#=RmOmVpTX~^siywbPmcK02hFJ5zB zE#}`|+EuxCyhoecM1E1PEYH0f$m&mBt}VP~n)`?fJsV;zcV!E`XiZ_azR81+pIE_X zUuF#q;UVV=GBeBuHpjci+av(o&V=;HIvY`W8)E;9l_aCJcW_C{w{l-BM{J!-$ z9K7#vv;qBm?N9SkB2=)B{+4f5)sx$$$foy)v>ZGNVcF^Wa(BkceMK;{5-NC7B9y$& zT^FTN^g1gVh<#bC=zkdyLq^eLD7w-$M5z>AX+?*8t4EX3npu|3ECWxXrt6pG_xCxk zA*Y!O1noi0?2T6=_w$o-aDXM`YdzF3mh|TKWUF}=ywieNfVyQqj{E_h4v!iXbuCdX zq9E1iJBQ)X()Ra&-;AoeBm$%+edi`+TP&^C56QBq#)}M)kr>R{d(^qg?2VRofCqeU zRO8|Za46fNZ#8Xc`^&ka@m$LdpWE{-`d6Jx<=39Wr`wkr^7e{6on}~5u8I`@4yg5I zBzxo8DtUmFa=&MZ%(htyArm%yDc4P6Ys*4`iESui-=WCeR>V>$f|wf7_ysmwd%8-s z=wE9-zjgti?i$METl86MGBjqyIn57gO6DNBb%u~@8 z{VV!GgSmXVy{$2Qg5Ld^LPcR8cX7cixG8tT2XvKEq0)22({CtAf#33-KPf?QlI8WS zJx-N%#2_{rL^3xo+1sMb{Mw`SuUWfgOK~T^dz@MSO=8o0YgelLv&|qU5c=q+ zvQ7Knkr9c2-;4no^o;pq4`c%G?lC}NdfrTijp$)?AbX?!)g&CqY7yM-`7!A(i=g03 zSWo|I5)Ni>w9haJ>kW#jI!*bRK{}YVZ_NZt+uvh0Evjy+s=HDDs!`^ReTEtMJVk8g zPqFHTR9&0CH3Kcpm^gw4zr`?jf`cC`Rx+bm_A z$&#{m^sgwF&aX|Xoo%mIJNjg@6!vm+olTUqyYOs3g_CYGAQ6XrPvCx%h#C6UR;ZFM zdkABX&le$jTa=k!%WX+Cp?__Xyl(zDljJ9wB*u^LQTg&o!X*f?NupnUE&5lJ#LB!@ zW#W^>FxgG1EKCzl63_pyv));W-|%fqS#gqtweiO>pt}u-MGGKl8(4!q7B`b&?5wcGkB>3N;;A~=D87=)A79sl#D?xn(<&>`p4oB--{BLQ+l|Tj!L@;*VPPA-& zXnk1JK~OaNArwj$wRY2R+nbx(iCJzYkC$gr zLQ`&EUu>2|ZEqqR3P)SYZATU`t7lnsHrs@*Ts?MnXtfcoG1I;Pn7*|{7i@RG06;<^;IT0QJed>AwI**WRwEZpvP?eBkVozIiq9ku1K1?=XqPf_-dP z7Wr)B$cAEeFF^^5Iy`sP#UKth2rWb=1p5}Pb5ne_v2nVX-OGjs#n7sK?zM)2eLu^$ zVZdGqUq(lcEuWOjj@z`5&WFK|q6W;mHlo6Nz}o8M}mK{L(2 z#;UX90YT5b-zWJN*!8jw4cKh!e!Sms&|dCVfcn_O)mjeuKy^R9IpkmGmRtUH#!w@9 zuekRuTIoJaI?|@Mex(gi-`cCU!&vVTbfmW0V9h4Q+`4>FAJ3$nRg87exQ* zP(+v)pAHj0?etzBGXz>CR*AX;YB24bk{c~~wUWo_V7hPZCBo`nUqheQYp1Ll)m2s3 zw|220KkqB;Grbj4PydHV_2YFVS>RvV)Tu!T`?<9& zWZT^ctGtj-_THi2esD}%bx)GjXDVy7QFxe?B4Zh`lI}H#x-Sa*0h`#}bf_^LRisGVH75aZb4heB!vwPhFC%eQT!+t1koD z*P_qSlOQzEw-%AK-CbdD`h+(97xC9K#s}gpg~|QSkY+M_3~SJ5bPD}ztntu^JI5M- zJAh)aMp4H%U2ChQj!3V+LkWT4Qk7f>d3`PV1Z7X~yGR<%9cx3HVLO^T{IDlf-BPPg zpA&J1^d$E#12e_Rc35zSBzxalsXcBcxyBv(6*8nexc#h{=@EV}mvjk|j60+>1l0k{ z59+pQ5eJlnNBN>^!o#G*efy6V9-xwT-&XPtgohUiwx}-iHH39_jPOu(eSTFv!&lnZ zVhd{|JVZZNM^=&Qz1C~@#(3Ho9_gXS`4;_aJo2sCFUTX-(4#2ifk!;eyF}VemI{v~ zdhbwzu|nTkB6zmDTgdBc(PxoI6jLN@jUNU)wjYnDjn5;SR9%Brr%&eiC_(En+90q) z4NRYal_q({nQjy&xz~;SeE!FNF$xZZ8SH)+Qpe-m;_O|g27dr#UyDA+@NN(peQR$M z;A#WZ=lHr&u-7jiSSS6cwf?qj=C%d0pnv}fv6_Olbkd-AfjenHibE>AFe9I7xA{!F zo140)R=53$m`37dDEVrdWGxN)#t9FqSTa9(1KNuLFrx|o%@Y4i?#gY0jmZ3Rd4+bvdIBLUYrAQts1m69@d*sfeZz_#7rh%3Z9S zlM-YJKX<3kf*VurG|NinYx~dHl`EjWC?ltpZw=*Dpo#Bj-)J2?PZapCP>mqoXAovw zxkH(LQ2gS3Lae4EOK>e`m*7rUef!1g+oJ?`uQGio4K4zd`QFJ=YdsT$WxIWf>9xHr z^MQ?&S~($d_3heF1&+DdgOP#__IAt0?AtNE?9W-Q)duw^^Mdjp0}z`&#CzE83a>f-VdAI`%Ml{tWOqQDJWb)MqsP{CNE1 zKWwCJ0RPB0O9-9IeFQzihU6#}?y-zS@4fovo#nZDg$+d%`0oS#2EZt=UhX`U==E$G zN`A7&9@8@{u%WuGw31vY1nSLux=Q-yCdtLLJ6Fl(G)HmJ#~UTr2SP}#a6bo1 z+PRsDLI#B0?(S9wgxBWF=$2CI8cXdk9YP7Y`p%$CX#VuAO$g|XwAR<6Pw7dFU}vb< z7X34$7WFG+3`w5OD%KrZ98l_^MLc@VmcS_Vnps3-pv7$h`rdlAs88l+J5#g&9{%Cr zz&(of({)E)3iR#mX`-3<2;bfvV%_UiJ@@*2o7ZttGfS zlo{Z(db*2a^_^RSyH}ZErsB#RJ6AhYxMu$_SM_V+x%$W27^jXmS9QvZ02~X<3HorD zl@DP=W3JjxWmA}j?gu{6>%*g`YBU2k3Bk_-+1H}aFwUi!>Ko`=i_k>=8Js?u(m@~A z2)vtgS={t}BH!?#%~UMYHY8eu-J!~;=)G4z#+#_mTKpaHnG#jwPt;70=?d|QiX|oO z9% zH-8fAXyHI^I<>(0B&S1qPjl=4Xj)MJ^MBJz4Ho$-BUstseTU_qA+wEJ`#Nf>$Up17 zj&=}~Lnh$izD|z#I*MJ%^l1BsEN)pS1V8Pw?FWfi+@ct^_*7|{4HHmZ+I?eB@rkZj zNUVyg^jWI%bXB>s2x7lUPpm4e?>`lcB^_+4!xGJ9OC zh|Kn#-282#8wa5eeM`G45XkQWmbug_Z`u+ZZLn;+rxDd;F`kOoATqnuX89t<{m3zD zltuJi4cYA_k}lSCND)0mpSZrHwr09*qDgJ7YC0*39O?1{mUJHw8k`vGwm6aoLy9=J z&r)G7MT}N1m-tk?6@~tN+alKbPlu2nD5Ip0i7|R|J{&p>D&}EO=kK|B0Dn5$UyG0% z%+DsWV^AJ-?8Vrv{0s9dj*9J*hOD@(&s-d_zpp{RsB|H|dR3vH)XXvLsHIbgm?$=t zmU>cbYKoc~#yBW62oM>}eb|7{LZh)X1%i->tDh> zqJ{*OJJlL;#Lw8?@6IDf_em1fI>jMvA)AhRm8N1|YL9vqZ%y}e0%@()gl_rPrm9=S zBm`2Q;vqe)BS=qcgDet&-JS0TwSn~o#KJ(>q`Ix{rIfGUsBiRfG4VKqoTpd54V?1T zcY3P=A0~nbvJrj*g^aoZ6XXd{5hj8nNJltt!)$95y6%WE6hb@n6!N{Pi6~@9%$^!i zNb$~gerowZ3NH@(xpr*o;<zq7m`HXD8 zhNW9tgrjln51Z^qud z8F_64=g*AsPnSn!6@|=jeI6yU7ONn`byv1c3B+y~3LlK1&Jom&`WLquP*E6zA#hv- zr9EF1u^^~eI78CCN@)5K_14ioZ{mG^7faWm*7W-51l1b$etO@JQX1N+egjwxkolRi zWHz?ZP3G6m6M8=6K;#Y~2VW9c*qix=UA9J7z` z8uh91D1$KeM^TA8)Jp0TiQx&ppOO%b;^?UVhY9xi$vz_xKxtv5rz!i1kR2$Xv?2w5 zN}d@Ir>c;#*m{9O6fTZ5FMDo!woSRwh^~%`Xd~qZxv5md{O!3zvu3@OA|yUs6cxd! z8RmIf-e#9lqC5!tWy99DRu*6P zm#R|9Kk#j{Kll;75A+eGqH4=_+iOneP(G*f-;I_3hLtCTF|^z*fX^vW8)yCMHA`+N z->K}&V&(rUlrN&*E{F!D(!PH5-l0OF{6^&-87u!rE1xK~zg__QC{aDvuiiUUD3rfl z*?*Z7>p$P3T!jBE0(ex3!e767?@%E-($(V?>dPB`>ITGD5+rRSK7LCQz6alSyG^66@awLwXt zow>^G@VRP+wLwXtL&qui>*V&e=(8w;Kd%CzLs2_N3HB2qBQ&J6(9mJZeqYEAEh#N@ zXqvK*vzGK(Z0QgyfpW$WMJ-JcY&v9wmXsD+s!{fzx3fKzdg%M4G})CPT}s)Hl8wiU zPisl6_Y;!5s7<;5{1T;ujX3AN=5vrkDR+u;A{%keUF)-uNh$Yc%VKYSu+w zOmrJP-Pu4xHazD7!Hkd)E`M8V1~cJ8QK52_!J(RVi}isU`4?~x8Js?W6C1cx46*g( zYIT??Do|udMZRc7^qH@nX#X@_+qvWu77Au(|LoogW~KHjy2Fa4D<>6OS3>pfSplSi zlZmL{e|Ep|rCgDQ&mU-{jE~jpKL#tkDh@Gb3S>vrVY0W>60WYIdf8;pY#y5?LMY z6O}_bT)D~pndznv`g%h*Ak1v*2K|}jyAfLa%6gA^AkbuxEF8i=o_<6EhR!S8v6tTG zmiFc@9-yOz&jJ+%*;std2IQ?w2J74EyWF8`%(fA2zcb*uF_P08O-^rYZrX_BTbIL@ zWO#k2$!e3~)ots@%QkLgAKv927=i2SJ2g}xHY%}dOGa%<_BU=YBlia0GpTAifyX-V zV0AgI>Xflp&evr#8|-k``fU9MvkJB$ zRU+z?kKTqhBf90%^**Or%oN2(#*A&xTl7ob+-IgI*S*f`$#&x1EL5f7I80P#pW>~C zl6^|YI|g%erh5BO@4+__f*Tq4N06dHd{kMz?8j0%+mj+xw9?x-55)Ljr;ht3rxC<9 zd){T15KfN_=Fa7qNiu&x$ux2!|qK1%?EZr}pt;wWW6%~ECeqA9Y zP*x}GL*WL>>J`648p!Cvfg!4y8r-q(7Z8(sF!w<-7o9V;ce45u`tY6#@4&FwIZ1V9 zc``q#_Z>c#PU{ENX@5oDnV808VPlb(ge6LMk)beEX|EI9Iq9<6|BCCErNPtAYVa#m za!mbNzw!i<`sy(fQGKG{t^=@6s$&d@cQJp!dMNW)?jY+~d7nO6)~eN{+Gi)qT2(io zIGTW3m5s}W#q$yx?KAQ9@?}ulPzM9DPH?yE^}2xQ4yHLnY@z=8N)VQGHlgGRedBh>?MxES|``~ zis*m5qDp^Dc8`8{JD`OhIG`b=rtu!Yxvb7N|9Q$Iwuj_G7Z{FPIG@V z2yx$7vPGo5JJb><+R4_tXpA&owV}#6-!gS^GX&n}I%Pe^Us+A`DF`;yv@%(I!_(hBtG5a1K`o+%Hs4B5uR8{){V<`6m zvo&@U)#BIbT< zf9vGV((9zc+|jHS)pWhDNh%BKRD8r(;$$>7qvq!OeRXk?y?|(gUdsn=0?BaV+Fi)y?51${L@75%DbR>@ z+%8NSu|K*p4N06CDU)7BsPS)9YpcJ`edr!L;%%DDb6gf#Y|v7sk8NHLW6G0_q;W;`C_%F!Zuj6-*eVf!Mmif*-wcS@ZVHox9b8jlO&4cd6z6s5d! z9rXw?5lO{|BO^2S($p@%P*0fxS-@yM0NW4(Li`?2xp;Kxpl$Ba0(HXdh2DW&=G zaiZlvj=c&ZEJy`Ei|_ zjZg^l1N$pKc4|Dn$h~ak^W%Xir9_^WJ0AC7y^O}=(5QNm$Hrq}l=8}vNA}f-`ajq^ z)=EHsTtAM9QeHXoya8+@>i+a^yMKH)ylr=DlJ)w3IDTN~yt@J3ltuF=~F~ z-1W@S;&`m&#{}ciJfQnliLOI3Tcj`M6Mg%a%80Pik2#oy_U3j1|GX1hcR5fzn68V| zGiC-hRX?!W$%-Ubk*=FG)i}5gcprrudHk`HTmIX7Kqjx(T`Xo@t6p&s_C=Ig*=uA_ z9aMBy4|<(xx6h^mDHX5fZT+}L0PZyv7$P|Tb?#mW=|O3C0>&Hnqe8TIrXAVm>?M(iPem<26r2~(^npK$@o8Vb%f zboY3>GQ`Dy%cB?nJv$ZPLvaQF#q)JRR{XaDD&xQB5I$(XL-|>DIjF8#vi;Ef)_RVP zjL;bB@(*|3hp(cRfudZ``W|IsUX55OyuR46j&(tyX#~zPQRyp3lwl z8tTNgf#u$Gqp=)NvZc*k9`-qXi#EA^d{%E}lbIXwRi^M!g>rwr!OH2HS^oFH6a9U; zFaND$?k6S{CKax;H}OVzX8s8?y%UN^)vFm7f)s= zje43LTbrNZ0CkV(+0*P8jUM7|>*`0Uuluph&q0ERArMiy7IN>%l_@rLtzC-N6{z-; z&-)3U+2#{;!vEVotuH)7@J@ASDFKRd@aF1W8AXnCC5m)0w?T$ZbK@#Ax7Sa9COgHj z=eoivI#;htE=ZH)D67i-p;Xm2Rb}|+&t6@s3JfUbC~v)C46jWfJIruRy9~ne-1(HH z`tG895&0P}FL~r;HsJzoxX)E}gB`c315b(1_&A3SH_gKk3lYKGCzwWHz5oo4ybf34VF-SRV7?Tqr_c-sH}gm8r8_gd^U!4aR6yAU@(dvv1UW^lGZ4n6Gr9;#yaq9X-SI>gLuaBuUOnGO83 z`(5lU=&7TMD0+mdRAjxY3Psji5k-%vl|Nop-bzSUk#(-yXJ*!^h{bXw{r#HhGsc&$ zO$)~rsobImUs$YG6IJRA!SDhQa3AFtj!{Guo|GXZ5`;-JU)m{QpLu-z(%3rB(Ydb3($zm5QHoe#dp+y&@IYfP+(PAGg1ijb?p`||1d)~+5H64_$ zG_1(08O7p6S`ZAhalr>JSmY8kJ%I0fbhm3l<;`0gRqD3iIN_Ahb%uAhgs6 zIRPW5HREZl?Y{e4O+f;26pkWh4UA<{l2JmkSR2x=Q5ZA{yu0uU}*Cr z)t5>0N@Ju|Ty=t;Y&<`->OOuQ!F2#knWiS}B~D%tbw?n5@NyL&^Sq2_0ftP9@+`m* zt2EC7=mzCzvB zOlC`udR0p!4%mQ=6vHth~m`MQZc~gRsQgT9+P1ytbKn+^Lu@z zmVTfr<*hFQqJ-wUPiX_g;Xo?Y#m3RQ8xfCN{WUym4Ohr#D0>@!WOvoP<&QXS7hb5> z-#cl@rcP~cDSOCTK+s?fH(dRR@Wxm6(adAJRAXhHia!#;PNkc03&qEr{t4@|7 z&f`D-646L|@7d|1WyefGX?kPw$-no}X6vblIb`oqvm!$VbmH6eB6zxzVZ@=pWd(ZuO$t0vU-r|v6Z5{Zv@TyylG_rKFF)~)UJHReQYl4Yfye^ zKlXrPseJ|ebCeA280jW;yU!w$WI9TNgqB}nR9^!~sSd*je|VXG7U^5k&mw)xbXbXY zX#%L(!E&>B9!r3j&fR^z^o!{k(K*MJDGUUD^!Lta*ITfj_7r;{TV*i!s1=3QU z!52scJF!TtByhC$1(H>h8Di z$|E0G!U?SlcE4bk#aA*wix;->8resA{C;)r_|G@7W%*Ij?|m(Q#mw+KfFBlq7JK5yfcD*V|2T1k?9DV@gc5%6NA-7j^v^wv z;AaSJw@MNuVC%(B-93$22P*jiDpUAXe5g1j4$DiiH=7>g`H`>ruf976|9*A78u_2>swZ@E;s_QkFLJibc z2%1I~SKvi^EHm=krS<|@@1C_=qd;cMqTFM~1U?5aFRd0=z$aAnm~q7D%w@tMGx*pt z;V?S0J(6v|wq4rMqNkpS9&Vl}w9;yJZC z`~&@+u_{T^4U4DJ9h-6=w#I507OSsZkXn8Ao+@}K#*M}5^;Qlmj_y})%WtI zq}sXSSa5;u2Hd{zG&IC|Sh3__5woV|YbN4*5-FCL?Trz zISlKGZ)^L$N@1$<;9~PXDwpmP6}`N?=xd{*`yfb06=eeNh0LU6>)zspb}b#HjcJ&n z@I%l)Ca0mng6;cObi+r*c|0~hF*=`VQnvm#ZxlmTTr&f?lD%HvI3wWJ*46qhCX$l9 zZgmn;`Q5$8ZZyBkgAx2mCbLHB_HL3G$)YhF>4`xPw=n89P+MlvGQ9F2z*`_WiDUFF z%wu9hd-Xd_q$RVbZ%))TrY~g{Xf4myY&L_VFNSi}%07=D zw4Y5pn4SNiHip@y$=1ZLTj&28i91|K6uy3Bd)cWx`p0{;-!8o;3N~Y&JY_{bm+^0D zU;3`a$3Zh!`Q^ZR17U4!ZW^dqvZolUjy|?#oZgbe+d_Zqok>fK`%>QrTWvYJ-zvm7 zH*{X>o&q~F3~`a(i_@L65iF2Tw|5LLa7Uc-{PwcM`r*LOZa=ax0BteRYK>-wx0nR9 zA1H&%HG}Pkz=}(&z%;cqGBCoH<;E%cA+S_bMqm|FRXl)cLg~N76%|bt?qfYh4a&4y znX$(4OyrB$d{}xd&ezkjS;{2RXTtL#=Zk zLKwL03MJvsCcAaHWmEY#HTE}CUExD&Lo3=MYs0u)ZE)NxYGc4Xw zUHMRwKh~6TqNWUrro=B&<3?C_xCAx3N|SHKgTO~ioO1^N1HqadOWc!>*vvAC>=OsL^~?RfpR(D; zHEr{EpXTZ*UpO+9oV$6Rza~ffv$n<#EMD8(7tzcYcr2*BZGPo6S4*LO9YUlQ_Uap9 zAM4sBr2FqH-OvZr%{6T2*NF=1YD36gzIi1bbB}rmQSUccl`!Gl0uwm=MH+x?1sS6)}KpnklwJ24#7MO9z>+6j7^QG}_7-zHx z7tfqNtKx#H3lKVk3taL?G3~++XIXLwuj(=7DaJ1xUHl{rW7+3_a`QmpgG8 z#CGqnf8VZuC4a8LNEO(`Xg+%Nvi&6ZPU|eb@4gfGE(EnP_?}q8_a?N7a(v%VhHtHY zg@@cD`P~CAPlRbiTP-4yyweu_9QXcqYARbaqI}FP%WRa&az~ecsFHCkgD916Za=3y z%hoXRn+Ld0joY#&FME`*t;jL64VHuZ9BaWgJgQ6|+48oz8Q%iMPB+c}xmPSVW`8o1 z=Lh4F?d}WUWuY)-A%O0aQ8FfTJ^%D1h8sI6Q6meE9WpHD$bi!g6C@jgd8e&$D>I`z z@XWTa$~4Q}c;w2<)K(YTWzh6 zR*Ux2?`x}lNYN@L1PLz{@x`-7je6py8YG4Qk^BG6IeQMFez->0?EujsE) zyrFRowG9Or^kLSbQwccvd`H*qjThKy-lX^T?Mv-VW;cVr5RZzCcqDg>?-xPIZqW;4 zc6bS82w-v$sRVdXlxjSo1ulAoY$gqeW`*^MOi`Rz56C2UNL@htiN*Go zw2dOPurLBRP07;ieV?Q*j7^s>!9!OJJRq9rdQW8f;>==0V{IKhlG#v>wC1?$ng!jdQ5;VJQfiFEJ*@8}{vh9L}SAqNCZR>I4p z^(v~#kLIBQdFq&p_Qif&d8^wsa@>BJ1EVYg86Pl{j}A>i0JHCs;$E~=>~EA zOYxIis#UF7y}}-;eIp;Dn2T|GlztmS1R)9=zu-TAy%ay9WiY11!Ea4RJ;Fn%xIT=| zO}Ka)+Ld}%D{!iS6Xs_hyVzZLMBz{5Pt%nLo&?!__1wFgZijZi5@x#cV*Nd(Y6_g* zaPg~XN%pdfK$V&m_7!{x%Mg2mSdVy*$_b+rbPv&?1qsq_dhySBNr&X2c zcXxJ1U-Gm0_wi3eQpG`Rn*v^$vdtHIDp^nH;B6p%qZ9_G%Yd-=C zs)P1zfV<^Sh-M4z*xq@7>EQ2P^s}RUdpq?Ro`F1_>^C6gCo$iPU3^>c=sdPlz@i%N z5(QHGXDmo@dzoVRG_{gN2nUDuf;Z}y(1Rc0J5|QIk7)Xx?48F2do*fz<0}eA{Foy! z2^@N86Le@6E)!h|{w#}=LY;wlCMP~bCocLG@1g!V=v_oVj6=}04hdg%bFwl#hd8M? z*Ng~I*S)ZR@tLd!T||fx(_M?&D-JTxz-&*3nPm_23k0O-X{RM!hBH)9^XPoS8>7`; z-oefij}Q4e$ca}hqXj=(wAnoIBY^@c)1yu4A$*0oO*}p%j#XNb3zDcXeV;w_0b8co z2`Vd<63)cA6Va6Ud_Io=7~SnLd5q@4LwiSQA&jU^*LLmW6{r>TIgsQo483`^!fvRq z>0uB4o7*DtLlG#1qPRW8&M%?}Asa>(I=jD}`1yHXaNZvh^UK(Pt;6g5l=nr5;m3g2___2{@KMW&)|bBb z8}(39q&HSt#ToslXn$X~JQIF_(72P0ibufAZ~yYK5-s%j{;W6*SmJ929NoMQ0Uk*b zUl-uUI0ObLUl$-FA$%^jxdPrVOh|qmU+4efI0UTuH}JIzxbZab4g2TzZ03Jd9Q0WG zj`dH%*ZF_XXRQD;{}$!z`hPef{Qd@XW0Lr~03)plSo3d`uM6-l&b;gsJIMv(;OiBb z8g-zDt*ZH4sO<v2jPiASo&S;61g!Nh z+D{$;1WhMje6M+HvH}JIzSacfr zhWqq0psZN*82i`l#{ysH{{VLT55&I}zQ+IK3E}rQphZdI>jI34Az-P0gMXuZ-GKIE z!O&2^K=^tE3gtT4<1y$1>0g9DGC-aGn_>u@cKJI0V@?B~bFGKZ82iUwe?$7%_S>+Z z{`flkkH-?Q=HCLJKSEDr^46OzbKY~ng3JbYxXlX zA$+6$H2XQ=GK(Lhe~a=Bd|iOYVh9YtzX@Lx;HHG|_4?EJ9~*-{ApbhP&j0?QW(5qy zzk#pu|JZ5Z8v(dq1GXpzJr4gC_&Wb%VhC9CZ-uY%zkkTU@*DU@1!@)WSd#d<0A*$Z z1MzQ^uRHMQgz)tW)cD^&I3f9Ue4YQ_nh6ZZzk#n+K-p>Fb6Cp;Y^)hOUi>lo@4Efz z?C*D;hW!1@*VX@6Lik4gY5Kn@Nqk*^(Pjd1^sn=8l&=f0538nn127;yr(|vc9y6oI z^IxNU9bf0a%uL|)%h&lI9T%UMMU&C7<99Rn2h&Z$_np5u1-{Px`txs;udDyDgzz~@a|JAlK_9Su9be~vObmem^l$1v zX%(K4h=x3K)=oy?ng_Xn)c`_#Df!{aR$k z?$dq=4IzG=s{I-hLm&?S{ma+c-;WFro&9+F)A5b^*Yy8blK8s)l$i+(#J^F#E&#sz zYzQzQK9|HCfcEp;C2cDA^zn86DfL)aU;_A}cCp^w7oT!wu*}4B$USV%8a~k&-G*k+ z$AYT1sI2cv#Ptfiv0!B_ox9PjG`C^08JM`B(wDLz-Vw z+Ak+7v=n((9S{wR-Y)jiIVX|6e2~;c`#bCbhq8lZ!*lBz*Ipj`bO@e$eFs-!i>w*= z2+Vwf?_kKckuu;na>Bli*r|avbtFl&vNO;PispRL?Gf|~`38XCaHJi{+mLeB(SA0F zZ1wdbf842zz#sb@2m2|Wg?#_OM|m!2geA#6`R>~LK^~h}kOWWrS&$0PY%6g-yi>uk zDo%TmgS~`7N4@XwW;)++I)6gy!QYX#@F(^O8s?DiIeaxIghVq3fBTHG;F-{Z-IT9J zIXR5-O_6_4?_2NQuwXqlD-6|njij|xh6!ykF7mKv|9Es#^!GxHmjPKYbOp0?+91 z9iws&5r^kjrqG5>vo(E-=TT$X`1|A2ZOzde+V({o>I@1y0SVlY?^Qi*u$5iNyPU6@ zQoffgUc?hD;2%^Hwu5?d8@(gk4>v{~S1b=ve3iGU#xuh|m3*<|Jql>RYx_C!GyCMa z5D3xZ`^6|Htq2>rDV2@*Ey#>IaO?tkv^?6}A&o`_Py$dd!wJ>4p*-I7vNI9PIy?%SX`)>8z&v{yW;0BsbNLW& zHW~4zreili`iGk^odN;D<<_$lejP#z?IZkQ9sfJWd47=#8(PM|_~30W7!STWRcT{0 z@3h(49eAn;KtajxJU`%)KXFI}72A;iLT7|$kLH^!P&^Lupls(|>=4i@{&dq!yx$dI z$M4`)1xBzb;zc$I@a_Lg0`=oV{y0@Cs(6tIhmoX*?+Ipd+8}2OKSEECs#eeUYYOtn zfn$%G$P28ufEBsE;!#d#JkePr=)mnknVtl~;hFRzSLgH*x}V32&D1zNPZ5V-8 z*}~pXAIzu^%l!eU2iR378wAxxJqx!jDQ%QV#E%+7z8H2cxY!+7hKo8@zdT$@%F*nL z^7~zEE^!!RgvNVzE@_$!AVtD{?A`#Iw2VTA)+7o)(BLWGn{y)w*PTV8_p-l3DKQ1; z@FY+#JDbYD7PXX4lEjpksi_F?r=uU}rt)?}H+1%g;D&-USIm5@FP=&<(E@e;AP?sW zOw!kIH6gV3c>E4MHtWZ;^c4CL@(!c(5eJZ$pU**?-q{jp2Ms#Xy?WRTG~=`}-`Cqv z?5szlkDYbj!+XBtw<~gXm=enHIUITb)%H+(+=I+;bvNaP!Gd9-a4d)x}HeXC=r^+@qA2_iuxP2CP)=zhwqFzn)RfCOWNB53xq)lkL&1>?T&Ih5g zdqj_FuEuB(o63bssf$xeThg{MKWV#14e~9()FI-ZD#xLPXfe>S>7kCzL2P2wbVnv; z;)nJ(%B|_d(osF_QhSe@_P|h-f=TLbgIg_r52XL7&e_;SQAG!bzzvkatQah7+Jevg z1wkw}Ld9>78nBB{SDWUZBoFK%-((Lkr#Ssrbaymkz@~m^xkG5VsE79AF>C;oTT>-8 z_8n{~{3J3g%IU_#sRg`80f#dORIQJoGh@;(^p`);nqQN>U#X1Xd%t^?qARfro$Nj* zx~oE5@)$c-!{FD8$$UWAKam!aQasRaMOSI4(*j<~vFFN8XI%ad-!AAbc9{ z(P=hxbQ&K<@{yo6_~YLnM(A zL$HR|rY3%Vn(%zS0`wQ35`1{&o5~|HDobUgQ7Je@>+z0cGOT z#PDyxYX($&n(!L`XP*jQ%s6W7>$9n_yTUPij?C-`+*^(QOMm|%d@-8{0%`FGnC0tV zzL-r0{u>zTQE#trxQNlG1->SCT|)SxI?M|2C5f*qz!8UlrTj+ux&mnYYNddI@HGY0 zCWOz;D@Oh}=+^o-rqd1i;}EdsUoYQ~p9YW?1~3r5E`LJ!94kitIOuWY*YOSc;}Eds z-@w-#eG58Tr!T*O&#&M>wWon^#P`_sT%h~npvTB>fp5qkhk#jrD|}u4Q3K0wg|Ew> z5WeAnd_58hn3*KLt^m6=0c-h<@^uGj&ahO#fcTmMf|MKk>46U zp8Pt#QUBHi;>d5{3!8Sb=HZFRZ{YJQ^8eGo7qFK8Z;jo@|NG_m{UlV@| zX37WZ|L_kMV^+$PkH$ZQP17K?3E><5r~7}B___k@)OH_A8c-({(Q0rB(9#ntqH{8UoYQ~e`q4|8~D2X3E^|B82`6Mk0-y5Z`8jvfjIIT_?iPW z4@pFR1D{`!{|}7cfBejA-x%6E*|0;WnEyBheza@uWV;T=5-`huDtt{14k`7}YLAgW7CpxP``4fFUcxuz-=B#5 zdijR@N#g7BCxp+jV&soSA4q;3-;jS_BJvyfngb|F;_LFC2ENh!^a}v4SafUoE$|Kb z_YN$-6}~QilK8s(3E>+KD2&_5h9-%xD`3ZmW(8RKzahU-zU}}GN#bh?n3E8`?tr@d zG3W!;zeNDp@j)W;>*X8rCyB4ipAbIBG6#U6G3W!zuj3o_|9&F!8~B<7G$e_y%YPd9 zyez%@V;0{PgB{!d*WQ|D)*TlarA$-ICbo);dUsu46 zcg+g0_J3V|qkLTf4N2l_3Ye1+KIg=207GNY2dY0S|KF2{{CfF@{7K^L@+XAPv0~(p zK_5_l9p9*b*DX+Z5BU{{w(k{ z@s%X;HSw=Y2;cBO-T#xs*A=kiZLtC1ODBrOEB=I!`%t;7e_di|!81#Ya&&vPb zN<@CWd_(>u@pbtV!sl2q{vU%rp!_<%QU7lyBENyJIY2{__`3XY@uMu7=g;)^TdRIo z40f#lp9)_Wf9Ec<_%ZrBCB7!Uk|e$+{&flA8~&#$U}%!~x&n6WG%LXD{}%EaEwwt?lh!q??b5?_};A$-FDH3t}yB)+bI?JXt+ zSo^;rzfr#K0HGxDH3iI02w!(VU4AqAfc0+?0Jd*UM1H+|L;fW3b@>y*=UC3l{QU7lwBENyJIY1~$d|m$2z~^OI4giLlvE#M>rP$4e{&-8>*X8r zCyB4ipAbIBijm)pKCt{czES^8iO6r@b4_3ZAe1D&F8^uZb69KtH)F^3|Ni*8_&XX+ z;>XjU1->SJLz4KK_;V7%H~dfc|0MBs1#Exaq<}d7ughE`LJ!94p5E&FBNmuj3o_|5_sQ8~B<7gp$P9<&TRmN;viS z-;6BwW9jF?M{CFuUzdL8t0w9D#E(;yuh+hkB)%s7bqV1c?x&gm&?ND71?>2jSphNr z-(P;Cd|d$zN#bh?n3E7bXUS~-Lu1fm?caib9p8}ul|@C9+qe+K zs0Dx_N#g4Y*#1wG0<8Vtkl!d@4*;Pg@ihg^P6%IjKwW+_`hfLs)&6ftM1H+|L;fW3 zb@>y*=UC3l{QU5O`BENyJIY1~$d|m$2z~^OI_y5h<@!IcGj{pB*5(9#n|B{IOdijR@N#g7BCxp+jV*KBXKCt{czES^wPDFkKUvq#^ zlK8s(aq$I&<@jBzeU}-z@A&@|_`38v|74QBPy9F)z9zkrB)%s7bqV1c?x!hWXp;E4 z0(ShbSphNr-(P;CeBJyTlEl{(Fef2=-Tid=W6)#m--3S~-;n=*5|Q7)*9@Q`Nqk-Y zgz!0*+5Lycpbsd&j&I2Sd?NB2_`3W_;_LFC2EH-=>_7gGL60N91->Ewa|6q7g|Ew> zB)%?xLimOQY7Q_YNqk)a+yC370Bip@y*=UC3l{QUA{-BENyJIY1~$d|m$2z~^OI_y5h<@!IcG zj{l!Ai62jY{ma*@zadF{P5e0t;T!&^+kcYyM*XihDIkvj>+&1r>k0@ZiLWVOc0%}^ zlNkFqqYqerR{sBoMC8}YH{?$eUza~2e2x_(zZrdC`E`7w{+~`negmItg2w+z;_LFC z20n+i_J1>WT>tNnuZzFqDUneq7UfQQvRSe`he~8G5+B0=!3R>zBYRB@_V4i{``choyxtD9`rkm*zgye zteW=Fo*6drF^yt6TvfZ*4qMgk3+Rk;)BEVj;?0$gjlY28?Clvi4)<^<*vTg22wFAh zl$Z9}!gF0M=~Hl=C>#ITcdD|LoiWp9!(pZJJvp8g4rRKhIgEdbTB01rG50A3_{FaS z{H?|9E%fC~6$}G{y{D>bx6hd(4Ju(h_>xAMvUM>XeJTJ@Bw+3YOiTJqI>A)DY)PS; z_DAttBP8ClIup6)2%p8EWBBucTv2p0&gjRX{j6k|&9+O!TS<5oQM~DW@ce|gOT#;d<3%gv z8sPB?QL3D!>|A_-lM0kuT&0GZfB7k|l{EnEqem>z#p=}~P&>@6?AcN5g0OAX>Q zaVPurjVU1FQt};g>v#C{MQFO?R%IF|UEUk=-WuY?;q+@F4SN$OZuf$d+(y6OuLgV7 zV1^p>aEds}4u^irTe3sG9y%~voMO#6Dd|;$E@iGW_buke>GGAf5_M&Uy3$3wc+{1^ zcd|hOd2v(=a>tbUHC4{@ac+38iN418p z&}f7e-?l~DMdb$O;}B?HI&XWeOgt%ke!B z{LSEhh06FP*V;SRah2nNygCQp=pbVXx>)ab^gR{re_>y*zk)Q$o<2!u7iZCF-Y}dW zW+}I4tF0)_V6UVUo}tY0D67celz&Gql~1a{G#!uO`__^^e%C&a(Iv6fbVYtAi@dwddaGUPQZML z5_E>r*^4*^U#WhSv|Z?6f52VnMY^M?C16=t2Z;<(oZe!mGz8{b*BJaJzq~oOF$z|~ zmJ(dh>E-yr5o`h7&vk_Ai5{r2nFgW3N|D2RSaK^(@@j`IczAJndl7L8@FGWK4>w_) zrOgdZUdj-wSS~aGGwB5H{Hq5U`S@niRf`L3I31iEHELWe>|?^X)L>=+#?E|1cpJ{! zj=FHu_Ga&}oRu?e!PFzo?RV2#itO`ABc-{jyi@fa4Q8>F5}U1*{%f((Ctuhj`0$Rr zC1YrFq@cUdB}-S8u)#QkyF}T`cH<=M680#aht1wVt;t(Fb&XYNpcEOQ6lQr_q#=Hm z;zj%kt<4Ipbt%oLit^@4SB0}24dtVyKq+oha~r`yE=qSl(&%jop3TB_L6? zl|v{TIN3}1lz_a&6|Kqg_K$#4nOQNOm^%S*?w_q7mwUk59L&ipcS+;e#}HmHH=q7v zL3~>e`pIoW?xy2u$~O7qaZMkm+g*>?o}6imq`kcRr!#Hc({t7ZFDB5@1e&32 zYdV%Dw~lLSO}9J30&pV-%+INo#^62Cm~AG@co2%yj3qzX=8$cft!4Zav@foT3X<|oz~?sRcIO41#OqcV@yn=H zAz%sp$BGexp?fmoCG0c2tju0yZ}wNFuugDYR)%(yy@khk#?JmPJW+bW`1DcqOVo{cw}g z1fM9WOsSX%RiOh%-`Z?RuScg8p-{LBKHd@;Mr?fi6R?F(GPvnx$@j(0=i8gR(`>(- zX-nDE1(Lzh@-TjRb!Ym0FcQN&~@6?L6S=7_&^0N-q`Ys-Z;A`t0 zpb~Y)nvU^!745|%%*oI0?NwFV{L1UYbq8@(iI9^q86PmJqvxTz@o0v^b(8QHRTQe5 zh>K8NEBy^0q`!~srN2+UM}J@1O@Ck8g}=)lc%+B_ggf}pliT=D-4_1yY$N~q^Q-uI z;=#I3{3t$0xY*IcOG>e&*g|y-Peb7@dN;c_6mG*s3uo#qhpn-NGmG{RfNfw@9W@@^ zEqp<2uR1CRS7FY$UmcZ=8#FDhx&uLHWh(pqkD;#$qM(k-!Ye>z;s?!Q?wgC)*<0LtGw53%%Jn&pqfJn+P0DFV!RJ6~ z8>PA8LGWven6~gUIi?>all~N;bhNr7k%7i8iFiz@M-|1Jq(JOueyD~G!H6La*Pq{J2nR}q&<{a12&78e6 z8-~c6Q?A%4t&mxYbcJ{t{8DC)6=#$xCz?KW+CQQnkNu;_*d=nKLmIAOyYqD}!!h}=n)|lA*-`T`7ot^}(+m3NUlEZ;H?@0k>B41dWZRN(fx4(UTySy; z{r!&r?Zw~bjmugKZ0j@c#mF%&3xA70EWlMZu2T3_4z8}|SL1QD{sRC{#6?TmB>esN zM+AH&u3pEBmb59jI+tHf#noTl$2VcPH?Uu$x>)*ZI557#w%&z0meN>wmCbhGlYZZ8 zk*9S$flj}4spvP$Z9VwV#5eAVj-2hy+Pe{QhhyK=oQ2Ee)^*F|o^{f@95`EU>)hA4 z@5Y?WkJjXPKDr~vgF47Wg`gpqrvAIVZqGgE(03+XIW>n-x79UG;A@?{+Xk=o<&z4J)9+Q z^~EUK)opW1_=aPbE&sPE6e-kTry6WigRSbQiEsoOB`9j3CFMmL`fY_?qS2bhsh^@$ zZJg?dt7s!ZEzZbIg9CEoU_X2JBAe~#-m*~DnsgXLuoTf~mO?Gl7>Ub1`-Mtpfy z9_h@yplihlG-Z4w@h5166x4)%PYy5ab3x-aVYHA#&%H;p0PxBY&l7EfQ9rC`OXwI1|%Al6K7>10_-N6zJ0x>2G`#k>nkSgqJ^|$!i$okP) zFMt8CM&8%-sKsqc=juUa`2_Rv#&c3qCUsKJx?<;|gnlM27 zM(}Vm{@sdyci^9de{1ls7XN;Of6#Rnbe)CYO#GsW`*{X_Gw|!duLr*_{JQY##IF;- z4*WV|>qhA4MbO)bf7|fyAko(9rqB)znCgPxLt0ZkKsLaLXEAlhqYh1pc$5~I+1$0C zjk4K_+_i6tpGU>dZ1MAQ2AUMig7}>CE3 zk!4OxYO@8k!2lR+2|xo9FgyeRLo5LX34oyh7#f$KPg02=m-j9g=f?$LmnF5A0f^#; z0brOVz@q{H!}hY_mH?{+fExhrxctoH{CK=~d5E7f4~q0yQoC4C8v&pZmHo0vOL3kR|eNl27ogxsr^<^8wG$-mH?{-z?lFz(-NRm0GtJY zv*Pk|1?MNzdsimsClkP#med9dYWQGsnY9Bl#CV851^{C$DYOWHu>cqwm!CfXNLilc zy(>#v0cu$Q&gutT*Bz|F%d_$FY^#^I;N>}Zd5+b~8F)DkFUR$JDSSM5o_(`@$AshF z<8JwW^z-a3_P1qqocm|{VgG8*Yv10Fkhrz|E!-*oHgBL!y34)c8~27l+k|frH1<$j z+8n;|3|09Ce7=v;KEun;tX^)!%g^!hbE}t+~wkqof*et%y<1?A*w7tiB~7_YGe$SIk&HUIuKfE521-oO_cI}{806Z^3s#=wqs04Np!@dLm_0iXqd*eIs4Gl;Vj@dhFq zI}{80v-1%KZ_rK$*s%@(n*>1o0Pv&$&;o!pJF5Yt_`miBzSh{GSkRvxnj!%^onXg0 z0DMmX#18<&1%MU+tl4SDJc8ms;td?p*r8a^pPeSafgSjNAddeFfK&Lt0MPv3nw^_C zJ4d~NqdeRo7A&V&(4U{n1+^aVV;ulI0w8_>_!^T6Ag=`gYkqdn%!B`gH*i8z55jgU$0Qv*e2mmb%^ar>_0BFI$njJ3(nhn155fa?BHiVy;u+aV$xAsrGfloAs zKe6QJ@KG-Pr(oDRSnL)6@q@(+0zeBE)(kfQNb!H}4ScS#L!E~H(*Ktrrga?p156hH z@qj1J70MN zUuo=EcN}I4Vp_+cKRf3OfcU{8RRCzg!kV2!-;#E|@dm!p*s<<7yaYICN9#EBXXjx7 z5I^Uej>83b{;y>;U9M{xi-EsIeC$?PcIP_OfPyoaa7B>n2Em&By^F079Q~W2Fc>^ciwO!o& zafSZGgm2unA0Q6I^e5bPBQXcizKO?&kG+A9xl%s{{Ku9ax%&vOj?6K0Eiz! zel7sC2x2Y8Z2(gIpLqkHX-cIbM}M777sRxlM}L590T4fesNZmbvX6ID^DgMLWz+rAYh$hRe#~!~D)U>Wge|}a7fcPOKAON%wV$IJ)&d;~r zz_*%utcM;BK}_p<^k?VOPAGbe239*EI~ zm=V~Ffk)kc_&msTye~I!V5aeoYnp=r3k5cdtM3v9RHK3I(j?b-s{@l^%3{r48wK3`X08-)AYaep1| zOL4zi#>Di>0^6%U#U%CG0$cli1-4?`UyA!Y+~0)z9l-+I?@-47pv)a8Bf9G4non7I z$agw{bee9g%b6Fx8b0ESYgqVdUxwMPQugGfHe22j2U3N4tL&jAj>?qzes=u|zOLqN z#**%uca>5s=F=Kz&^ck2qx~|PP8+1$fF;h(2}oD&>fUUZrYj4Ow%JQ*PZ>PjN&b9X z)92~kGp}$|OJ^zXcz54DLg}o&dPp!$^>yVQDDZx;;&5JhPY~&aUG4i(m9=|Tf6Zor zU9mpa{xdx5p5;n$*ZzYly42x)7ioXxUG2}(Z8?=Tp~=3v=|mce3THh@sZ&TSQtZ6g zNhtQ7%2Zku>t$7U32}Tq!E9v~>dtB378zVUWk}Gj`keXRrWHqy&T`qZk%yE|7)Y7w zWkmvsXTxEc@al~=OpfOHoU1&_4X*Acr{p}^WJ4<{*_ByHBSpd8GbcG55|M;~Tuh7M zT}p9}y=n0htO_E{sGib{mSM%WPnyxZ%QT@yn$hQnv^t7hM5~Q;R{^(hedI<*+7&s}u~ z+;wN7I4pX%KZm-@?MB9{O6gZFo)$I|+Q33On>!JCnE0>7b{?pew66dxhr~KJPvdnm z<`$sm15|)T6NB1)1U%Q3t+Y&N<~7wmO+4{LI$(Ftk==cTn$GPG1>5q19_gyQV1{%> zUNAE_IhLK;Xc@0hh&9Ri2e?V*HnIrlz|b<;t6)P|WoArXcMT@fC_&Lk&7*uI*l2{K z^$?n{PaUmN_i=z2~@8tmmdH?XwGkL1>`9YdM6{RKyfBLX}(;K(zq}0B9!JzPX!|;CUPc_qJU5hENIm0^Hhx_ zJ-wwa$gl@p$fs7J=g(Svt#BjS76UU-8MYMIST3+PXTVNdZNU+!Kc0%i86nW-%8Ux< zVieMXB59L@TI^YUHKNA^rbbfwo(N{+-4DD#&!fQ% z)!wUqpWXfMXaGaiPxvUMsyA|jx4dV?4Rzb4p(X6@3sK>isjZT$dVnbn&fP;{t7pP- zLN8&R7jRp>7uhDlQl%d#Z+lx1$hM^v_fFX7ZCT-0s=6WVxLq@@o75rhaC*#PSNliW6U6QaDzS(v@fo-nrOCRaiz$}m zAYVF|AyQ_u+5O1JGP}i?52Jc!e*+qL+1+y=jjYtPk4xF0I}dL4OHy(>0HuGJ>fBZauaNO|_j$W&aRgFO4Y z$Q8Ike|k0=0#RDT-QWS0jH^ckJ^9n2>AdpZ6&4K!Fm8vHLv!(%bh zq|2S&e{0H{jp{cm@6h{NOlf};Qj(%w99DWSRPLP5@}O+eWcLhYp|6_H-huP+y8i#1 zg`UM;fZ>@rn-S#qvL@P`a~gKKm7NixDp7m$Db|2HQxqkf24m zKY)22JvBHQ z4@X@61AEYe%0^P?khUQ9VB|J7KQy-SomROqrTHkWN86;#hEyb?g3K34mj%+nqnptR z*raEcDR@Ej-@?oy6^DGzKmfU$?4v5=ew39-bBd(AB0MdX&OMm+==(El*x7jK<{T#; z0jzRVrIWqBhASvi#4#&Ju`>R^6S)eR?(eL%*#Nt*HF6Q|n#EmYED|j*fZMJ^TY%1H zNh!RV{gJ=yDJxsD*vLZDQ{Xya9OjWg^}CvJMdpG8Pl1E0Aqx&IBLX~X(IN-#)hmft z%N)33z93tJ>$-Kvr zCQKRGQeaul)SPvx$UEK*6MY_l)xmN5j?2@W$VRrg>t+D@6$-TBVYguKKzly!0oA!K zI1%UTxNX4;BU2P4_sPZHPg0{98D+wIS@?5 z+1D`7o1%U$Ph*tt?5@3!Fgl#>zuXLmpPA#hpn9CmHjVxS-H>9L;>gkRox`{0ID-q? zp9hZ*Me(I862VPtUjW>w>aGBHv8p=+{`zo@D z%>!g)Y^+MHb@^Cq8EieGi>6D8nEwZTzFeEUK9>SFs?SfrQLH}0cp~)akLojh-=&#t zGi>|R$3JTQ-A~WfHTWtZUpa$ou$naZGVTvtI)*^E@B5Ym_Z-@{PmR3E#^KfJsq9Cw zMA>o#Rb6HO2Yuz$C9ki~41N6#?8NG;98awEb+V7X9suMk=Wu;JMEVNh-a=m|p|7v+ zJzafW6-$)m1M~lfzV`he^i>DksD0fBc4GB)DW3H8*Y=-k{yHJXUkz{d1M8LHTz5~A z?uv20>gvAUda>rM2QFime_XV`rf!dPTW(_m0!VFR@XVUyJWG4HmZhE6etQ_5U*(v5+_B>FqxA5Ojj4pgfIOvBjFvRbBM*P_*#N^6E3`^=Nscgx}#SJ=lv_&v1!(6ZC9~YKs*j$nystR?Z)cTu)ZkYhyFcr8ia1%CYPip{b*$Lg@85 ze*t6vgxRe3&>p#Oo{B;_*}DYAZiDG?w83mMJwU1VkXTUtAU}J79zDGm_OSjS{`l3& zyU8{t@4{d9yoB>3X#S;@S4X;^b^aE%ch+O@@yjsRp*WSnq2h!70DI;Mkbx;LWtieH z!GA#T-S`u&TTF?tU8u5VR{saAo<4)Yv;S5VqaSn)&>NU=EB45tr#@a`(M^$|cUE6*ldh%doVgBflawJhIRo?9HQxY< z>VS3^<#eaR{<;S_rEf6Fpx7`Qhr1N1?K%E9RXPB-*7xsVB%;_9+qB{vX0%F~(`bSz zIDx%^fGt1u5NWdgK^Q*!2R+!xAFOq;KjJQpZd502>Zb`aGUyYTa1kWqmpg0LIjZq` zUAlYI-Oh+zxf@3hw6UM)Xxs+9m=j%!(+Sq5c~?2sq_Gv`VOyJ8?O5utZ&NNuA0Cwj z2f*1Y4g{3Y-OdU-Zs+5@Dy2BsZ-79?92uhqI~XOLa-*R~f(->*dV+0{Uu&@d4sD}S z(^xuCL63#Oax)lKz}{~3DGeDn<1Q*=vtkodZ^0?@YL7j51>!)>vFx;8jg~w$$Ihi+ zXU(zm@Ebf!UY&*MGFA)h-0jmt^{!M1)r7MTnk$_Zo+Z%I`)A=vu@e(em(=8OeV?aH z&qC#mhj-&g4v8^G6V!nMVX=;r} z2{@G5PUXrg6xVS34lIb^M1^km*KY0FiI4eRV%P-D;F4?lSG_^YDTm?)X-j$`K`;}P^JMB!qp3g+P5O9WE zCvOGtx`Po12&G_-9$4N%YyP@;QG*ZraB%|9+jPK8HGGjR1ZVQbhrt(Z*t~=DfC%NM zi{f6D4JX!e0fYkS(2P($!Lqiks=BLkVnsbEwfaoF-iIkfXaO7N<)yo9$}G&<9#mIi ze7MEWCcQ>3g8lid9W8=VT@MmCG=v@CcW4oCx0}6*yU>gDj%}tF#hy?-y`w6D*M#WU z5iAR3VbqB|YZ;|%Ey#+=cW#J3K^$XmK@Gfy)`5il6j=ZounaI)v({0K8*+;q$SrPg zDvLex(pF66wt5R)cW2V+9nFg0;oY$|ABT6W^D2c-<@(*u09vb3_As=C0WC#)ZsS2` z)H+&x9+0)M4E&+Rseg`wv8cY*$bSosP#B#BzW1^0W-fTS!`S z4L8XGc`Xcms#2ISjobO~Y23^QP2*OcBUkOhAeG`cc2Ta(WG7*%6n}8SiKm2}0RF;r_v*uv94=e z?Z6%^S7#XXkO!hsrtrYLvwch||ehE8AfABG>0PBP4N-+nQ(J1sNk!}n-p~-8{}FUP&>x_cv8k(~z$I+WG*l(lD%NE<+;#U6 zp>&A5Ms9JIMxMwk%?wUqk415%AAq5-c5@?$5R@pDUC){Em#_(fU?h+Imj-$<@D^w{ zStREyx=9+d_CgOt3AI#;|y5G=goB;jm3^ai7BCux9j6Oqfx;*-h$SiW_KN zs8>qE>Lku)DRL?cT;ZEXU>OI&GMG_CITY(IVCr#DvD!955z=m0Xo+lQ6}SIiIh`l^|-9O;=@8 zZz*UmiP%-l8137D=jgG~jCBcnoDxrGIVz|(4)4pyb8PV?j;|A|df$QvdCPdHY7jbr zKLm1g;wuoKxL9+IotxHvR9q=zgHV?nt8tB{lBAwJq5e3ssFM$SIhbIb;rdTLrchOxnMbpX@?EUqy+u&p5#ZcZVu#k66@IoGS zvPEgJA!jI+1ju4QvI}`pqQzLlGKug;-X;vgCCmtO{V($S(J&k=O$KkkzT|Oh&xQ>t z*V`Qx8&|?F&c*(Fyc$+0H+xVkpRzwXi8bo82YSfZE85Us3m3n~a=LLQM+bZoy0!5%wUk~6OL5=-Iy4aWwZTd{;dDrSfSsJpttx{|rPJ$cbIZR0 z5Sq-qLGA}@aOs`pShoh}K2fVX3tebd*SPi$92bOkIlRz8>w_J5a=yAUORmK7=ouvM!6V4}O8m z5*8xxTKEoyP`1Q@KR3~z1^5$fcjw?zuF5gm-V$W61YHysa@gj-5kr}kD%=Y$>0&ip zNSsoZ#hwFg*t~qN%eL}D;?P}pF?>aH;vQcD6wmn|c;8(y zq&q)5#a;I+XrOz#W0`b59c$&Tm2oeF>tI!-iYnyNtw$Cqf@7poUX2*T3Dg{?hIqw7 z>Ss#x^74XL$oF{cD<#!QV{b%TLEg0oP6=iY}#)j$#2(RZpy%!H?dGjoc?&ziZfw~(noJuvVZ$>WK zGLq6-d%V_9bMR}uoaQ{7FOJlG73QG|{C47$^%FcK=7 zMhR9$e}!;F4QOUXHn@sgv^wf~u(a8MjINTXRHH~_r4w@bfrE`S|W`NNBK7bNgl@a)_x2#Vdx``zXd3bXdnA%4rfYz zkJv|x4|9uqD7RSsi+UIWt9_^T@`)KLpTL~FON0eq#4(VQn85JqRH72biGbUwWo zsJK>F-oc!Y;H`#%-X7c zk}_&k8~wWEYmtgm%F=%+5J>y%9AK5OUlCmenXywn@RkJYF7O~o<?vEFoN8^Jg6E$Bl&J3Rhkq^*ML#E{G@` z*iQk>UHdOQV2!W>buyu|k%)T&fOE?1{GLkXC9xyes3rV*J-5V9agUhH3uBR0G#w@_ zt+?U^obezCP6Gj$>Uu3u7HQVK7c*T^>%KD9x`zl9P#R0t{RQ2|ST~|_WDxr$o>Kx1 z+3xCFzb`_#c&Pgt=D1$<_~F+YIlAr41Hj9-A( zm(D}EvzHx0&j1l&_maiRp>jN1phU!pD8V$^!*2_)e*vPr3`d)~M4GKQ+-&`nUm*ky zyOREnnnZuko=ATukEg%Wa`1QA1Ec)>XV^^sb9OfWNz39t7i99EOEd8E#Di%?_)&be z^;7w;V|_k;F@LxIdb+P`g|b@G>LDB*TlO@)Tt5|eIF|~42h&+)X;<>M(PP&_{1CIJ z$0Ndp_$g-M?6URM077{C?p$~ay7T-Pvx=MH1L6=fc^UyA+ZQnV2&RH)$DCqjI(r7k z-0X&Oc;1QsY0AQtPo@M1cURX!aVf~DIhh*F>dv2;BAtn2&7K7)PActTPY_NS4gtz4 zVGq$YTB8bh5gcoX2+c|lc4Z=7cEDUP57(2XIO;fgo>^SB71_2n1Q=H-y9zy@GRnNe z4p*8<#020*vZ3P+U?Rh;=Om6dQc;m|HirNBZLuM`*l4}~=lG?wh}Jm0X{T6(=Z!Hx`g#~PMYi)38^c-rtVX3%@&2k`TD&i7{L)VplnEyOaXv@Q_PpNXv1jN;~6H75!a2p&BS+ZU8pu;ULocHMl9x^W7I2f2RE(cLE zDvl6c0z^8+DwMt$D=Q|((2YU+I2i($MZSmG459}IPa`45A>+=Lj~I)E7#m*r*=(9k z;fH)t1ylWIRP3et9fNvDVslknsOlhW^)^YUol>h>y_2)CcHjwff!zBvaBq3PXT6hIEdnSQ7J-hw=8`xZ-Fy7!q4UqXVh6bhY~AC(|J`H z-A$>I+t0oieHFA1#&lLyFHf^9jMV00M9|8~saL*O!e;V9nzc&C0tmX*PMp=-hQx8- zLH0P_H-q^-E5Hn0j3c^wt>P%f~KVaX4J`ANkmbRl_TXErdcHZ?@rG zd2`xKU{ww;^KKj4cz%=I=)?@`Sr~x8o6w0=q>F~3kVT@Z=ww{y? zpmQo6B_Uo3?8h-L(kjO+T#P*Bmx*p9jjJl;N|l?kk-k-PjLtq?^JV49#eld45T(jy z!}pcr@)zTpzDQRbgQ!-V-mSbTP7PfS^n#jWjX+rQ))H7rGkXyZS3Rxs*9c{p$NdaZ z1Zy$ija`9Ly|ivU`V?F~Z|92hYEHh0vR92!-kQJ&0LqQ8lpvp$Xl~9 zl%V6cHLu~}C8O$0xzXci>@MSlac3a5P{T z|0c9zw8&SWF2~W_Z}>w?k?}>7LQxwdBn0lni zg1W{v`RiuUIpR3-_GIuangft>l=N5@Hqlp;z(NUU;cE65{uQMzv0?@%?IKAL;)|Wp zwUCSDY42f_Xp^!l=$E~VPLsR^-9H=vy#Nj5JarU3m$%T4Aa)dk4%ANGLYH&~Ke)D3 zc~{xSj*G|G9S|yV^<`;7AC|^)mO5!l^g|W~<}1`U&YSOY*UrO5lj;1@aW z2lH?NgnJscEek0&@1;KAV>$}x3e z&@qdO_$#qP>4JPSO@@2JPWL}ubGw@ylGD9ur`$d%G8PB8qCDyHhMm>zKd3%78qZhR z<@Rj3X}h;L2ExiwW9T!VcpmNN zU=dSbFqyoxoX2tY@Suv;YBUQee)hi@NT9=I>NbcYE6--Ze#Ie-*$}qyKX(9|XXSL>}C0v}V+ zhvQ=o(Y?1{$!n1i5iT3-^@Wa#r?3nhE_C_XotPXKtAE=eu8M^qU+WCn*M^-0t!sXj zdq6pY9f|hIq$-O2*gi*XQhN1VM|EVy)_yB8v+HW%@FZTuE>wj7)&J+i7w zGcd}z7E>@$-mVN?a{*uL=t&I{mHfzHN{Mpd(rIw@;jaZ((pBInGKAn-(y1kxA)m0j zANUakB3|L@s5?*+5;aD|4%1;#>?Hb&qKhcwdpvi*KaoRCQ}MI~sk|#xjxB|qk(9#f zYqF)|4e3*VAmvS6Ax)gR3Ww~k!Bn_8$=dTQcT$A*<*>LGpDP8u_lO74B_)J4KP^qLynkBPL>3cF8BAtiBquq5+;}tfWy6g54aIwo1-Tl)39_|M(aJBEkZ@15d zfbmZOk>CC@E?Rt@z_hhfNqC*=u0wJWweWK5NqJjp2p{LbidSpz(9KW?-?2(tT34Zj z>}Uy*pv-QRZkE|_$yX#@PW+uEvvhaea1cJ~bJ-dZg$f5(xgyu+m3IZF)-3H+U#CS& z-i3->MGr3;T!p@wcyOVHb4E=u?`1|Z=n29Dl5Ms}2GLX8Kz-0&-40ZEUU{dx7AA_A zD(b1yUQ%%@2K(%-r=Sd4k#W~m<2{aD)j+DRnHF3gg-)xe0B{M*`h65S=#salQ8_l8 zPdpv-HOu+?UZi4iYV_X8->0HstQ=IahQB|kzduvn%K5}3hF0K|bEGkB4mvGni}^P` zaYrNWb1JH#EHo78mSWieZH1rBzz`en;Hs2kl#K>lO}p_Cco_C+p^sJE8CvKFWrh|y zLkqJ)MIOG4f@y(l3XXJuNA3YWaKv~kcNrW74P?xy@onfsA2nu5i;w`2PkRxIo~MyO zaC*4#J2dpG&IlKx+ke?oP@uUyv?KzHkNgfo9Aq)lkOKotKI+7`09YY^m%IK6qb$|z%s;B0EZmIIg)*AUZymgd$hto0>JDvk&2S|>)=TB%5=8uLr~-Q zp{#Ul3vr~2K?4mqMA1{zX@I=M|iz*sgI z3^prOZP3lMTTvj*q+!H>lvEtCnv;RF)XW9*{DDBlEnD^R1s_i2ZV4fe^w!V?po7y| zb0#SZku8!lF?Tdh%al)^l)RvErF{IPDX3>< zhLe?`t$i8S{H6jokr!`$FpbFKO9`mUX3C8{I^B_uCmRV)%0+qT?mBa~vHg#!$Rw)B zRF~sJI39cphh2kM2h%L)Fc2e@x)HI**1P~@oXW+>8bW%Lde?Y1DhjySVOvmAI$!w` zn?4WZ?#b=WRn>RUZ9!k;OXaZA1l9b#o>Cj|c01my>gSkYgpw#9sA5n{0cH$;6yd9P zC*<`K9P&EQIZ2O8sBt{K4$`Y(p)Gg$AKlH!@t9QJG3}J?RTW*oIx` zhzwJ%4Xt&Ct_dy93@vt`^O1`5GfbW3FN#jEh~XWMt(PvMXiqaT6k$e}uy?RRfH@=; z9LvixZSsXSd70Bz2F-L&$5&m_>4nh{lKu5j%jB%`v~v_ab7- zB)wTp*CwhuBO@{LYw$VoB@^}%RlzkXDB;UM>%P#&**FOxA2U>)%0BG*Sck-fi5T&u zq(>$+*i{@x@iwDL;2A&+j%2A{gT$0eFe~-;i`VjD2%W&c?tOh7v8H1+njm4bZy<7u zQ7qQ!8UQyK{@I8+{w0b!`piVAjy^rX z?m+eyWHx|?T$F$Cynk+wM|dqQRSef9-Jys_b|}BP41ul zc`!nFPTh$23T$$iGzaxQgrCq$Ty-yTm5R@LyhLB=2)#tgY+ng9l!FFdnjFhwN8G!>M^#;m|C7ul8Inn6gam?u1`SFL*l3_7 zhG;Mkq7n>7@=yY_#WanNQkVg(1O`vWW^x?My}#Pq{?uN*YJc|j<-IM6RwN;q5cFyg ztBHUHrF!C_8ikSoG4uPbeP)uN_VN4O{{udmbI#stzt&!R?X~w_do4nA)%~}%Cc0nP z7bI0<@sHA(~I)- zxtn&%b0eBJ@~n0@{hDWRyHGgu;su^(wf{}y001FXMAooMS_VnOE;@|HILOd`Kngg4v$%pzRB*+>!! zNR!J$%Kc8c@k69u&KQ}RF6dO8P6{z6wJaKLR)C!fP6DljR;~KyQIO7El*rIxuQpHg zEno4@wVEg7>)vIv9PW5if10&>|IoNb3@}GWxWJ!yebh7B-g0C3ClHFVPpl2CasTiP zWxJc+<5wHH)qUUdfNMkFcHci&rrV+Kc)zC&-RYgB4Sm-gc!aopA*TQ5f?&mP3aldFnKoSo zU^2!pRs983#fDCm16|DiKl0%_$A9|UzFRGF;@f7{nP_D!$#YIhpE!eoW{E;6IdC5@kwF<& zJehG6Rz+CER~}Z`gj9+Ov`WMcj`62MbO9O@JB2ZzlC|{%TE;%9HE6g7YYp>?@I3L0 zV?1qvqnx!?1lY6s92Q9@djiP5qO=fvYP{cAwjuJkcP$z=9Wr=+iXgLSSOV=oMUr}L4CuVPH?~Yc zzp-Q8IfFeo-5GpqtZ|XSunmfMOCQ2Y??FxVwXM-LjvUU_6bBwueCTY_&^wdbeep9? zr9-~sx}uw~Vk%gAh?i*Z9FC7^*-vjQ=SKc30SL4$TRW8-d{`04kp9-@c)P-8bIKBP zXQ=piR!2#sV&EZY`Qh3wo#6cj^p&8$;?K?YR)&?cEM5I}#AFwkS6y32czi)Y-YdQn zS&A?1A2MethBY>TErw+#TtShn*2CTWT4dnzO$jUE4&P%0;(@_fqcrzi zVI_j-JJkfFB10je3}Zd~*PGxvAAlAwL30SMqR6cmEOE`z4aB#SmGCuUsLH&K8Hn(b=|XFJEJuz7HE_ z{QZ)@LH=T2y2e(@-+JQIibGt`hUc}iX=nVPhuLc0^SsJ3dDz&%w)9yaD}w3b)C$)QCaLJL&r z1(8tidh=xG)tQg_c zCJF%?0cpu%E7@ssnCHm-I%6`3Ae3{%AnM7kNc%)p-ec`p8Qk)RER+EZ zma**UqTcYeZQ*c1d8K`@()cBtFGNS&HA+IKajVb+$H1yKR?v&%gXl3CFev$h`X1v1 zPSem4d7Jxkwm!50Ca+X#BB-)F@Ixs(RWLA$0KKz+1}qY9m+QMRE3-L{>I+TdRZWcC zO)#E+hdeGcpYzKFiSzYkxJMQ9GymF(m8>i0h}+2_`%8M8F`I_5YSylvqaXLhci88I z*2T!$eKR*QVp^QdDJWlaZuChO;)>t#?N6TG$XVmHn-N}wRgl9qkLW>{eBsm^rd&j4fb@z&naOE zuqpAU4XalUhHdfsZoU)cJ2CQYD~UN7x8^~VsJyAnVLo?*J+v@}Yo4>L63@bt=o3ZF zacIY8k8K%1HnJzy=)z+fPBD)zMKOPAc#R{RZCnN|Fo$!);tZFYeQ!rLHMwP+e7|Y{ zSDCq(<;iPbe}tAsa43IGQgorwT0;zmACJOV>LY%^u?b9Gg9}QFgrZ2cv!`g`!3;awrQUX^KYE zBNV3{%ZyOhA&i-X?X*g^3bPsFMl*K!IGx2}Bo~4$~rR;YtH8k=GDmLJW2 zA-bb7?(r$&As;Mrt?y>bR%=b_h{vX)2XZTu)EAnqT>8-y)V%@+idOxp&xKjoRa~?W zdzSm$0fZ!FvZ`75OfmWeVV@(Z)wFA^BhsAI(27_QaHgq-q(VAVrF;r;H~knnMlU<6 zePhjM{Vlxv5iuP?FCFpOC2|X>;Z|sJWN&7lV`FnXZULW+97?&H76UF2bj?VY|45&| zZA~*rVs=~q6~xGPr$47FX|Gphht9v`h+(a<-1Hk9C4&dgJE*{9ciykeI(Rf2PU3I6sg@uN3kq^+5|KqCcMJ*28w zs7r0gt~5@(Amr<^b6v66g|O(0MdOa1_>Z|!?5?4bvXCkIF&!I?rY7ahndK2}k4 z-u{iQEsnhQwecPCStVwo^!8xSqyvL*Vi6XAN)+OxxP26-#d{H|$&tab(l~ z!DR!u$vXgLCk0;HbpDn&*vi@|?C-7y>M(RDPym&TgStSV64#;<-jE2?GiO0@QYJ|{ zN@8qhjfwH+;ZcsBs`u#Y9Qr93`x0Xs9E3ZubBs&hQUffQ9oBX!UUZ4<_KqvvWBE_TorCB{8TUNvA;5oquM*mjn5eDV~iAI z5nR)KU9JRr*jrx3tV`r56Wxf8+^7hX{kcg2c38#STV+iO-H}OQ>S)!Eql>xRVq z?eooQNtRpO=YFV78yem;C$BiQan_YDc@tX_7IC%gRP)LaHA8gEwX#&KMlwM(sR_bk za)+3?gBUe=h|xWX{n4OQZfyG4ymhqY!oP=Z^{&*0ioG{$Lv=o8pA0plL`9wqg*Fs8 zw4rZ!&)0?)dMyySu1w|;!Du^BW_I)r(71>VkdHa#OCs(ZQk5Df7+E<+u2YHVbhDZO zrU{7HgA6?*&VDh!xE<35Ea6dp)xxvZ8tASAP>- zF0kRWO_qW|T75d79P`T!1rf@bzPj7{e@eYsAFPt~!2*axmIih1S#8)qLs+w!X!;ye z_7T{(Z1pDQPnUcF3*T;)&o5njPrv`@zSQ$0al=nDbf=HO=* zf93o|eV~4+KUIMyzbMS#@TaQs9S8UK{i#Osew-qH#ozDwd!D~N{JqTI>->GdAAK^7 zzWHzZQuNo4<7aX7e}NH~(#as&Zl8RcV}jg?$(n*qC;H@*dw5aGE&r(cCZvP+n3*j3bp!Yd8nN#j3J?^F-5T-A2qP!DKK?RV^#FR98JgCsE zaG(QXDFx0pCXj_XfA_kK&${JZ&fb%mv5em}!gM%R=Q`vx)V*ss8yCf+D(iqr)Mu{> zmByeOyCgkp=-Rw9sNQa#Ud5#9GWN_+GYd@EEVJ|xW!ZNZio>FecAhAsP1f5uyVdt& zM_--ZDpUFqZ9(*;GrSz-S5z!Dmazc3Xg4y6ochkB)RrpD*dsQw?yq`>hUc3eI>fPA+|iP%*9&n`PDSd(jP#-hH13e(E?RN9P*?Kc`z-+%W)D}nV8Jr>WnPagQ0228lli8euIJ4@*BE|-_AfLzj9$PxLrIY2Dgiq z{owYE{IYSKVf+WgH~z{^@n$uZ$eH~-v;aBSI)r*pL51)8iG2VaXQtuk= zOo_YcNfmjm*Q1?T?DLKUq>O%c^lU9R#Q0Br&3AriQLKOdT;JqyK+0v~dHYY2%75xR-W&a=zUwXXpW5gx^`ENtO*I#esK%MO+L?OJ z9naj(&CxR(ypu-)(pdAt(4rXs{M)_%V%1?JAdNO%BO$5LNJzf?I|Y&^jHnNVs^HF2 zK73R4fY7m?9Sk^lV&*!i0uaVdUU4wEy@Z*QvNV)|%FIn3ueL@?W1SC?{cilf+i}31higD6aL*GJQnB&rh)i<+g(e!85?(X}= z?g_`Yn~UY>b_Uf$ZG|BJPK5=1r_{pTREIp+AL1wYfNI4~snHyFU@nL87Kz35U(UN6 zr>Q8+vjlDero%R;5S3XKnB|)u4oNM~YT*hL3L-7sDUCrZT~kmD8r5*~wg?HTP{vPP ziwf5jKM4n_N!08}3I&9na4NG&9)%U5ol<^idnUieJ*Q>-iuPsG{j}n&3LGZRs(>1$ z56P`+=A0HiAR~O-UTQ!_)Rn4ici>Nu^4ayGcO-0l?@6&%HLU_#R2F})vU0CBQrRO+ zx_=c77KU3wg763$T=u_-hP%gd{sB3kRo6F&8;6Dm?uwv6+bIZ!hE~F}t&Y4^$W2Nu zb_cE{^z(R7enqVAci3FfJ%S+WUe}P8Ns!`EsjkKXTELx&D&iQ-KU;*6`QghN$R0xDEbvW!O=_tlqiXOpSIrD$` zc~}hADfW2!cab>I#m<1jNT=fO^d-3q)3R-bd&w*jqwiGgNKIK)R;8?|$9RtY3RDcO zQHv&=HBm%HskE$h;O)`wiIy z9?HPLi2}OY9gvH{?iU`GA&8#_l=Bji{&0ou8@?HPgA9 zHuKROkWCUb$hY{csd&<81>fY(NONEY03kK*%dO$x8AvDSYVZ<%>R0@RR32~{2`)E^ z{A}my>I0mjqf%1RKbfL5V~x8hpkC}Kpa3h{5_d-fo)>n6f?W<%LtccTybRYJ35gsr z+Jb2W>1y7wCY}By#hK6UpGE$wSFp2~$hKmKVlQD1o{JAPV8rwy&cR?L{;O(z6aKTd zq@(zQ470A~0g)KY6(tMi_^!c?!c{FP{!_Kyua{i8f1RVH&2+TvZrOij_l65E-96Ik zei~nB-TJGbTkrf`%xmwp8TL?7+#zTBqU(Id6|b37+)wXq=|+$~lJL72B42yYispVo zt?wZbg3hPT!R<1cS`$~lx@r`e5H7JM1T4IEc^$ut`P{fH|m zjAydbN1?bVR?S7Rn=GQ)*r}!lp=oX=M5r_|Qef;zd#9Qtze{v~CP3rIUb*qMoa)zD zVrhTe=ZpMzInlRrwCd-bsQp@IwpeQ#j%ggtpP_B*-@}h=bE|RLzmGXR91!WPf0w*k zL#y0qP-W&Sxz646K0{=b5+YPjwLG5L2Y^7eZ4kc{}8*1BL!|NBJf0mT6* zx`(e0#ROuaQ!{!TA{54qvB|&P4bP)n9~rwlMOI@jxDJdo;mst8X9U}r^HgJXjdyuu z#ws_;*QsIVZrTR|tmyCh=nI)U=DS0`CsbErpT2WGLGH%~aVTatZJNhQLjeIR6q%jNH^Hk+dtLA< zO9mcMi?2nNz;3QuFcV%VBL7UzuZAN0{S9Lft$w`+e!D36@J7i{$o6`)PM1U)+r>vIeS!ZB*a=SI_hn=>g$v{*5tr`sV9HEeUYEzyxT)yfi{2 z)-3)*GOMXE(<&>>;}|LQ^I2J8-85iZVW&v0F)a1Bi^yt(9|t&E%%!@T+K~>D=BtMK z>@0=-J5zzQu^SQc@FM4|=G15)n(iu4&VW_oTjVe$=f74Mv%e!J3d%l<6GfjOH_?^l zM-D>T`V-9f5cl?((A?jR=WmIJpUMn=R%F+?woepzqcd@N;K5KkHZV zvv~~>-zIF!cM03Ffv_!G)`XrGVh!z*-)nu3>6D4Fjz7s&jbqxeX*hbK8f*t)n^JH8 zslJyjgq(d@`?Mo&dHhr#$~m2dAp*BN^!-V1`mSR~S${=4vL#q%n7Onc$lA{iyS*oid$|L;?-&m3066|QfMx}5`Q~BCz0HFq?Ic8~gFk3WI6_akcx9Tt z%p+)R7^%kkA=YKtFg(v_As1=mcSkdpO`~Sy4|XQ=j$?I3-N9UYiLpw`OE*e*MDD=J z=BDx1ZK{!yYN?1`Vh2a=`>5Nb36a~W9WAA3rN-bV>s%`r+h}oS!&U^l@Rkkb&|2OB zxE#4)!31-eEW0_c^?tpjATzeLd#Jg1gljsb4UQV`v{GM+zI(8nt<$O6yCcD69?^Kh zPv=&uWJUO97{B?0s_~C_ShrlPbCy|Fjm^3G?){i>@Nl$l$GoOc*^F}OhT;>jxbuzW zDxFIjxmvxlB2gxJ>SaG5rULtj_&j8;(A~kJlv!dK0RLb&rOejd_E)e}SnBn*T#Hgc zqW5-D2l_T@5bgpT$wlsLb`+(=CC;xM!6~D=WpT<(0W1{2tD=DZ#*r9+5k_nP&rHPh zq(ELQkW&RRH3|t7!j3>)oLCVmGjJ8=Dc2LYe-}<`R_AvJ(m*hZxubgD8ea3tJnkQS zTf!1z$_7G3@s5*XO!$3-6UvQsH;G8jX;m_Y+x@wCMfE!!rrn=$2J@F3vfJB(wPNWa zug9%*Q?%TVidk^3yXiN4EJ*gcn(c)PL2f@P25hzul;-VSHw85&@oAd4P+~gliKY*{ zn|FkZ8Oxz!qa5qG#o@E-9ksOtFE17woY-hCwialuqW#YEoI^6#qn|G zOk8aG;#I^W4KWR2%Wq>5+u(GK3U&ZrNPW=hao@8D!ZXwK1grH0(nf49w8T(%{BRbZ zkPe`Y?trvV_CfaYyuKx=scU0=VgJ2+u$Sz9y32H<=DB5(`1ee~XKzx0|Jia@jyA8+ zGRgh)KKBbj`DEdkY$QA@#CR!5&F?Q{f^^t>%z{yZ$t=`{Vw;!7ZJN+BNq0Bjlrob5 zyD$26abZ@EIdQP(rY(Q%p$!lA8J~viW zuF0}z2vsC1^H)MfO(fQeJy>{9gc2*-j%N}0I6}Ea5z4YCq0B-NXeiP9pBN;n3)+QP zhJ;w;-Qf<@@Di*& z)-MZvPIl!CgnPlQGCRFQ-;K^r-A`Mbdppn3nX&%`@FaG)#+eKIUjU%)78-@Kv<7C> zDaQRdb74af^F?AVEZ3pTg+Z}6qb>8C*R>D^USs8UwaRTWrI}Ba8z0;teAB0c&1^`GPG1v7>tLLt^7*pq>rz^&rmxG(N2jkHN6&=~C%|mS9i0@rI5%NofMzaR z;OaM>^{S8KiM}wdv}QjR($ zJ4ZY}TN<-Jzg^LnklN5UXt3~^hvB_CzNr%&u;gug7^{Cp*B9K5LxR%OP+%H0K-aHa zj}OmH2!=BF45$4h!su5451b11I$0q#l@k(9`;o{=4=Ze`402k7fd!-#R(S659~5;ulwF7$Qal_0pW-{ zVKjRpFI#s?CgDjo+uGfFkCjVSkMzoH!pk8Z$=4bsW8Hj>s;@xAsHQQ!-FKx5lR~pp zOK@E5zDE`>{Takq1A`&&4#;sut~9BP@UbRIJ+vnz{TG^4qCcQwt-f?WGjZXN}%87E5vTWCbgc7e3NqMCxOKWT%#BSwuE>z5YTJFFHw3ENw{ zE9YcoW&JYFVMCz-lkpk~NxoTa>RM&F-d0{2ky_Ni?ZNA;vI;WVorq)|<)Nl|lK9I8 zu-9eZF1?!f_Li4SmnH95luyWVYhYWgw+6K8<3w;^UQHPxNh)$PyJx(Gv!evVRS$(s z?Fkui(1Hwyv-8(>N|?=eyS7uoc;_(BvnNR)GiK^fBw13wnC=y`fnutGziZ)#H*Geix88uLMb#$5z$K7t&q)%Eo?F=d7)3_ zg$JL4l|@&xk63AqfXYrOrZDq;$!c~30IX(fN8zm1>?gHq4*Q(E@TKNOdltcHzI-)% z*^uPITJ0#S+0(xs#Z0U!^vlG7^Js(;2QDln*N8S97jequZV5J0Hacix&OvNI@hl8( z#5|^lRZFpRLbU@wFF!;9Q4C_H2qH=yu>}1Of|^8zRUrcOPYMX#K`RJ1F`oNX5H_x? zAXaT2mNKofi6KF4M;wFub4s1s5zpnNP8DSDii9|$A^ZCyA&zKBTfaRL6gw6ar-Cke zi4fzPoK-coqa%nR#cN%jCmqpOC-$}?p{NQ)Ut^!l@S+1xTQS@BtoVYvsLeYs-^NVk zy)a*{nR#7#Z9d#>J2j`>oWT>zQb$I#uGpZ{oEZ81Ea@e4KtM8vB^Q`Axn$(aMQfG( zLKXKOTR2wo540|anH2djwJz=y$wygg+mW~&=hh>A+*H3@f+kdF#%sYCF z)`wZytoG-^?A?36TIxN&)SFc5o3%AX@QMka_?h7|;c&8Gm5bFL`R0T!S&(ghG-I;P zSx&6hmyp%&O)K>#l={w{G1;7~$6thJESW4OSg&9=7@u34;Z5jWSl)Yq8FzSL`QZz= z#S_{3k`{bHT{xZ@nJdf@5R4eo?utrGcggrGMDm6@Qk&Qka90@LL6ob}-XHAW21kd0 zCZ8C=Y&xplw@&)0hJUfFX9LoeL>_ zlN)Jeu0vDb={p=(+E`>mhxqQrX6b0Ce9yL`%qzx+e*gSP==o=bIuFOqCmS>J?Cm=| zReOI#*}Zy_U5J;h8loGwo41^kkbbOwy!RtfmpXKTs4y3~b%w9)aDpreE!Wno!7(>P z4%Z&T^qU+T?s08B^$LC0n0y%Z)lmbg1^2x>|?6%mKCyU(<^}#Z-v4 zmt)D|Pj}ddnN9XKUYOO^RC~-D&pk=X-haojrrH572BMBptbhL<1Esz`Tu9(B`xv#a zJ;w9!1!zwlUx`_MF`?f>bwtDXGaXOp#Zcrq;5@^d#GTBYD(d}@*|0ph0`YqEDi;=b zy=j~A80EBYNjLUmKhUyvSle#wQ6DoXJVFi_rhyGO8sf|;kb!kckbZYG#G3K!ki|9F zvBb*}F7_1dqAF*(G0VWWyX(dBO+{=4xxA|jw4v#nK4MLvG@e&L1Q<9)g`T}aMj>l| zy?B~zAF?~97iXYwtrut3GwDICv#@52&Y;l=m4}M^(0f~r94eY4qJ%h`$+YHh@sQ~9 zIbOVp^2`UL35_3-L{>ft039yQAW`(%LVotWMOYoc;Y#XZ%$Xfa$0xa`_an-LxmoqT%p1Y0LnwfeoQ|rsB}rNMpp29 z99pF2S!_XHLVkw})6cGbp+{=Jj_v8SDn+JwZn+_r?>Zfss{ZRT3=zgiDE`}-*NrF3 znaKZCtG|a~De1kX*opVxbRF;RX!FO(H7pz>Z9U?qHA!vI?g$8vU^3^mtz3{1m)VJ8 zGa4=Xg4%W~2tRfb6xR?drkcxAb_}6HXZeYDG}z4#mEU;r8b1*eZei{%ae-!;6T)(s zuPCKUsSAT>nNtnK?7HMm>6&iigtN%7Pjms{ra)*h;LJ}1M<8g)uV zpBkB|`)_p(7QaGbEiMjPuU6sOSq zrPgroS7>yZ7cM>Aqe8*2@j8KRA3C@~#*8Wq;6uTZkag6@`_cywHx9dZ6%R)cwUp0; z?~V_6u$LWqb!qmZGS^`DMa9EOZCpY_&A0as*Lc9CXt%Nj;7vR@XBEusV6F4PlWk6~ z=fQXStPpzXK|Vw@0p@mKBt&ehPU!up*LeGr!##X4m-m_yfe7cUw|x^4t_Neg+-r@K zy9?e*xJQAvG&gP|8F&jAbMD_Pb6U5K*#J1FFA zcLXo{zn>E4JEu;6csT>i|7xuNgOT4|Z93}yaP_3R;KM5j?ESU;{^23A?)_8nf!q0b z@bJ!6JURkv__aOQ68Z+u?jzl&x^bVF>3);#`>jVD4!Yqjdk;3F-Z#&lX z7=R*AYWud-1#ilX@4Y=UzWo`!%!9KtwLOVs2~}O=5Es$Tae2h3fcA)ccYE*b z%$wWmbVp`gKFv74PV39?rZFzni))AQA49mw&FuQ;bap_53x%4C*eay-92X8#?-t5R! z-T=DV>)aD*9=|iQhYM{yrx&Pa)t`A!o6q~FZqMF2_qy)cb?(i(`8f5gEkn+`_w>i| z)y8IR0-FAFY-jAY{6A0;xAq3L`P5z0CD(W5ZF%pf?xhFo+&8_cy*s@1L)#fiKGC&o z&2cHQ@{imf%Y0xBRVTl}PuFV7h;bAW7)$JV)DJYcsla%T@!IcVGZVJiwT_SeW@ z!2^OXUOwe-AAbZcA0+K`ziLP|s9H|rs>8H9iW+KEJ&H2W_W^Nff|ELT^|U`ma1L&3 zPVy&Mcm*W!=$BX0?yhrxEK$_H+T`!WnKr6U=MUJaxuENypi3HdCcg$Yo%w&L>wYw`4MV+5P&Y;!Lqcb<~ z^~<5J6{bQ^HAAdMa(h?0qNH2ct8P7gvkT(8lbNU=zg&ifQ`5hW42<I@+i%T1I~U9)A@=!0mnAob2qn{1-WT7YqJE60MFRp(u!ZV%lEyK4(A0 z?BjcSpZZ?T`>eEX3l0{S+O>7JXZua-gb6p^7gKSbL0Zk(OIts#%)?c|$m zSb0D%6E`|#(2-1t=v{ye*dV~O=54bwA13^e6)vM}Ip~}PHxLFpu{xbvK{?Ce&NZ(C z#CWO^;BNj}q2oD^Seaz-KF`m)WJF=qqPp4%uy967sHQ5_e<8~H4A5} zCP_8pqx!%2dx<{=bDH4YVocRXpp(^O40%hIHO2(B?mew`)wL6oJ#m86D2`rhlP>$e?yoh;WBs*Jy^rVjp{J+;<CPye&Eg|6YGioVjMEG;!i|zj|8o%|_m#O6cVOM80_ijzyjRu6)xsO-hW& zH+`x>XUR7(qc6xe%$gJPXIWL9ldh`wH|3iQ1)}7eQ;PU4`G%aCBCC<6YLJ?$N9CHo z@WC`M6ZCkDN93A9w>A~FBy9ul5vlD>X3=#6F)|x^RK3=9Gj$2hCe9RG@=h@#_gFFy z?;r4v#PDU3%~=ACAP7(<@mbURGS&O2U_&L(5@;g0=p$SSG=ih3KqE+il}-C&1j(J!fM_XL}WJR>53HL32Qly$B!%tFlv>@MonJsP|bj%hj_c ztU5$wfg0pA!OmH7i(n}tw#2eF-S(~T zim0Z2=-GO@kC(MBaEb(8DdP!<@fjOmr$zVnn-?0F@zUF6PVGI?Yqa!VfpVO+-7!Ky zm-;)-&V-}aeEUe^pVbZpfvx;E-WCA%4&LtSJsR1|dGKUFwsK;8aaa7g_jG%8f8xh% z6tm~iBKs_dd&nt?O&T+jlkC^@%i;hz4!j|8^mzf7CaMJD|w-{a%4 zcPeL?HynOI+S8);mJ(aN=Pn3)Z&@(ny_)wNcDsUswSt8IBr&(Iq{(WRB0aiG;qFub zvIo*1;-~l53N37x1inVTbu$OH)Ft6?wJx8%nL_gqL3S+;$L)nQ$8T!v z;9E8|*3CVX+{3#$+k%$H9FA-K9Q0EW==Jf3lDm1wlHJ3y!-$>T^*l}n1hX-|bB9B? z^4cjq^TZSWyInC}X9(l?jrTn9#NpbOkZMp!ZDCfFTN$(zrhtob3+N?DOh|uSbOr|9VbmYJJgZ1#~gA-jybt97dHu5X}6lr(BqkuYum;(07AAb zLM-002xhcpQMUXP$WOWatdgHK(JKPo)=+1CIt(6sW&*D-JHatlvAx)nwVU%Dj)xkDQ1d+g@5GsxaWAElj0Yr`8V^V?w*pAz zvG2|5=K9f6W3$Rj-6x<1N|&D_`jflXU`aYEOc@7C@Yn|!F zKDdT*E#WHBMlv_O#vui!kF-n$$^Mo3i5{-dr+YZot$aaJNZ+hrtU3x1UjDae(2JSQ;|1kz_O4<8tde_#A`NXOH_@Z1+A+o&@`Yy@S< z_Iu3_*?z}`c;nHWgSpf9;HnXeiNEr2R(ig1It2&fVLHoL!1)SCHIU+5RpH$8y$-$8 zyt5(Qcy$I*`VeM&+(r@x2Rr2~SsJvoA< zCv(n*bBt`Rz1Ltc<7|hK$=z%jKKeR8w{@l3_j0*@nKP^0we_?OE7NNyXsxMe%$uX< zKTH@x1`FkKfvZX%$+`>oI>T)r}Y98Rn;B+<^l`RD`Bo zu1|s(^~&KOX8)F(@K-u6O#b`2(%=Yo{~TP1W}u zFhh%D9fJpEEZ&1s?Q`bJ|O+OdZOM8->GjYF==R5-B*$BCM~>_qTp z2X|F;es6RJE1XnIY?_QKwRT8*55G?*+yR-!v$%m%JJfc@(QtLp=emAH-rMVA^|$R< zT2-k?p7#bJZ{)p&1J^Q_{yj(D_nf}G7gU|kWUQN_zjWZE!8c}jsqbRD!#6`Jb-8(N z==wet{(Gyo5~b?eo7hOE5p{!i{dNQ)@hd1LVB7+)aK8VL*ml z`}G>2onk45^h@{^gI0Md6-9DF|~4Lk5*s7cj(0=gW-xa%#-hVKl7o$kPK;va2gxQI4uk5n-E zCiUChCsr&CzhT9zB$2!)lsnZYE`zN|?eS*mQY&9VM@kDV zfKreDu0mYpX{#I~Dn#4JWO}RUg5Y824Hbl=9X{vD2o9&s7wr&>%%zTyxt=EUj^Vn+ z=NwxaDouqkKKFY|d1{Xe6)|ZN`0OT zBXI~g;G2sVyxUq+xlk^pU_sid#^Y22-^Ah{YNHk>sXSJy$JF3EnQB+?^?MeIZbmd! zHmQOo7>M?EHaO~S889Ikn7ChiM8$}^-q zTsCm%XX?fNeA@?Z`(3Vj>Cs4Kgw2S0wJ4c|{>8QiCa`Qc@AQU3eP7nAZT;9P@hsFz zhr(L(F*ip%p>4xFf*zhod7TBr1M*q!==2-B$VZ%%bFJ?seHnx{6gNbLLN~auavWUf z3|+^IGq}*9t^OHD9x(0aehII4 z&>|=xZ-gB;gce^utc4YmUCE`M(6lpL>48B?dhYhrID^+agri*V8om4oB$V@ zBwQrHp@lQnP4hQS5-#%UIQ}p-RJ5%~f7Q%Tah}i(pJN_Ps?r2U$GKcN1T&$cD~5y4 z;NqBJ_}elUwwZ(13hQ`ppNBgnR zAV3>YO{IIe9mXPADTXp}fMh;f;^tJ7sJ_S)wKs74rpTGogU* z4T{-r5EHk;Z+#xSk2|8OKBEPeod~%;(eDye2Jcq*y`EoZWM%`c@loa+@6f0aXjRPl zm0i@{f8b+b&bbP$uLxR+qw#&?BJXm9B4}MQ4z1`q*n>ss!%CP!=8P!*q&}(`K$#Pk zWRDY8qqR-ZjtnqCL!A}ZYNs+Ps~VHESHcHA(#nRyW-?@_?c-*{fe&SxPF8%c7rCIq zq32<*_o5MQm?moNsli%jUe8)1ugAAVpDr2y6_{RNdVRN;cvZtu)>ukzlld->q?~Y8 zT<_WeQluG=pv|TCP!29B6QGF+B1RZjqS{rXU+)QGB-W$N4}1RcgTttcma z(JQ`*k&MZ-A!8+cvujbH3%*%)Lci%0$JJTLJ)cDAkKw)WG^Z zz9fJEopC+)^^~A6WYe#6>fd(+?{etZIrQ%fV{kXg8jngwDDygJ5P+ou5M1iySL(IG zqRga`HmH)TQjW%p{EbOAUy>p{M$N|)^7Jtx9iFhMxk!WtK$6D@bi&;tbA_I_s=B04 z2}K7!n(%cP8JCWef{DS!=g6Rk7y1V5`(<1cbOpougq{+*D<*gqSLe>nn=bP#=tkC3 z!UPxOXG)N;)u1zUjbn_9qcKzLY``3LtD2d(B>W_k;A1lFGAG4~bAf`#UWPy;+Hh67 zWKqqmSYrP}vFCE5f-d|5ud%G76br6Z;lu0~r-4rACB$ z%=4ptE32AV%Ia|B`J8J9qJHQ^M-PF*O*=h$3iyo;?^iIcwa20`TE72CA-cU&>*Z-Y z!cvzdfj3c=EI~EKt(ZZn-?krN&C8GRs8mdr4cFA)x{&X*pW$$77BT3otr3840ifmY z1*JB;kJQVHQ5wnD#Z@P+JB8CERMrg*>GcJ&x;nEJE2d84MroQ1#hinMxzmT}BzMz` zP-k%Z3Eo?ZJ^wbqQ_MWO10qU9JaEMMNG8rVdRPf=w0v(f4R z@SZogw#s;!sN8t(pZT~BOS>I>>O;oUJn*ahW+c<6RA?l#$M~Qxa~qGMy;j`kO_4ks zdqj&yO3)j7%zv$agy!$~k>CL1#o?OzC*}Kb`MyEEql>f)gqw&B>RCb6MB42a%Ma4+ z!)#{IcI6z~NyN7$qTQGQdMu_Ly(`vEj$_0{C}xtK#;>EHTw3H#lJT(h-OeWg#{H2` z3<(>1S?-GuklP>PE}T(Jr7Ddhv*o?NK;Bo}lH)c%#`xx10aGLZ zno8F4pIXn>fV=5DBDS6pJHGCwg}m24l~rW>Ln@=NVwde-5S@+RKB+JOwML8|UqS7; zWMA(9{DrB&R5sW;;->!uLJX%p#VDeHi|cBgR%=Pfk@v?bQm#yaHo4me*x2 z$9OZv&g2E$TtV$QH1{*f52|hg9W~|QuT@yrR}@PG_rIbpf_rZoAO9*Jpyh%H-hGqn z1?9$9AQWpu;{x7l#DJ)8#8a~a_O6w zYpZcisOPKb=@Na7{T(WlcVN@IVy?obZ(f~$Kl+xw37sXYHL@~S|HJ6_z4D!s|IhNBK>jU!hu5!W5qO{`xOugi zAdOraKENWVCRnnHHI`a=YWaJF0n-ClvRGmX>S1S?B`AvP>9P)cglrb%dt(+=8p|)G zhmm<>TH-Oh{$Yb-QI%0oB7F!8PWe6XTbSxgRt^>BHI+sd3G|*q952^+FXv*WD#EhB z>RlqnMADv!j?B?<^<#FT7$?{>w;%Vj{q$^D)yTMUCE+urayIP}TW8!3Y7HIGZ8fx` zJv>j!H)bm+c~uvlj#|{iil!o`wKABXf66MMQ=}*ybU3{eMARvEI)al>i}hc1p^wX^ zxy8f3yAUCugdlT4I6<`Zl{M|)GFQv_V#B7y$YyZK~_@!?`ub4-a^ zn0T5F;?b4$lkXS)GZ}K}cY^O<$;r`i4YqlhwP=~Ush?_KzY8_|1#CH$n8%lx@2QAx zBE;7L738LiRL~QSf!X5=JGNw@|ElHQQ&QWDN88m`6 z?C)njpLne*Ja+jtG^oq>iL`}2^e$6%bW(-u7fkRj3LNz2%T71I7a7;X(4~>dE$lA2 ztj2}8O%!dZnQY98fY?jI2}CV(mGoCKr;|LPBi42erAPvgvgJfeR@_2%b}hpeju~B8 zxRix+wn^zuXz*!vIxV)G4)?6AXr4apK@o<8DL}*8FVhLVQ{B1JU`uMmmB2E zhJ~S3RD>E&7>TeUamcjCl}}Z!UUwbxDwc@XU84`ReGnURxY>yO8b)9#2-jPA$Gu;P zB)5-LRZ0e3OsrN0rH{Q#S;2YT{30HSJ)kjh@zD$_rX6#!=AYL}?b!cd-=^Jn8T(Rf z-FjV}aRMQvW?p1nEEJzoiRjHgCJ|>8IK!(2T_F75RB4r;zdS_kk1>Tf`g1X#v z-zn?ysXlKTrD2sMtFvPNP(gWB1qSd>gx_F`1+09v-1sNipanU6%@BJdLs)n?0aW-6 z*f(cK!$ty!G_r*ZPeOcsp6v8?b2(NdaADoVm|F9CBkeV(L&;Ji#S9(*G>PYPJEGP+o19+9z&%fsls8QB(c>i0fRm*yO- zqF=t7Z~FlvPrZKcQ_}P8-W7E4&HBAEyYMxIFLvEm-3&UPmQ==nETB(o^n1nf#TdZV zV*uAHfbi3jpK-}p_%vQ6VXKv}h@1=bd-w1)XM~?}<4g_Ie(%e?@AC7Lh1U>61qlz5 zuebOLKi$fg@hY!awFtfNI$wH1e!;yoVoL5$q*gw6xpDcGVE*gIlYrIKgf^FV7CX6O zXWP1EXo$Jcdybw!-IJ&S_CquQ%3V3^orssKvEbV!m_sAnU;8>MjavDHcp}Rk8Ee&a zj7<7f43-~AbA_jr%ZFfZ^h4@2`q4V}5n4G~t-GyiP0;NTK<#cgX(B#jqTk#$pdMr` z4UUs6DQK)ZQjGxS=VT_As;!o){r^?16}K?VYTKECzfSdYD)sEVLGP?8F6Fj~V8*qw z^AODGOU`s^eD19yHa~sBU8@@SU5(zkg7vMqxmYEOtRJ(8F=jSE8Uv3`qn86EYcTD& z`F5Lknvo*GYi>tAaB>-KhAca9i}MRoklc8V`^9Qq7Am=2&+nlOL#{oHa{!1yZ8O^d z-F{S(`i{2Gc^qM#{0)b9ie_L3s8o6X*x_)X>%U{7`gL%|+`i)+c^B^|`ar$R;y6Jm znO0S9{M#}S9^KFE)!W#u7B}#lU2R7^No}Fco?rg*m(Lp1gBbzftXFnP!j{w+ECSr% z8w}k$ozEA9Pq(Bx30vYDjP7r5Jtl@h$1Zx|lRjXa<{~+sJi=+O)7!fwog7z)B$?CN z+!QwqvI}s;c%min5uhCb3CLioy)5+b#{^);)BUtPZ|{c5S#1U7p&unnd_%^K#ydC3 z;Bpn>6&m3Rg9PFAu25i@B$QT8$pVPABNk^jNouWB^9ibP!IRI-0j1YmeP zfO3SafQl4QreN*9Vkt)MBBl5j$4~dP+!rU=n&-$J=rjq+kRUQ@zAs+TWjZ^W)Qe4; z`hr<$VX-rClzje`8s~Im`i|z!^8}#&uQ4jlW%iPR%jC$Q5JHhb zag^Suc~pRci|UbR<;8atP+>pO=+e-8%d!Y|g85)MzyCa=8x|`%$ zY`FL+p40LNcwPI!*0AxJEUni7xiu^%qTEfZd3Qh4$u!xgFz0T%kq|MmgghbRLWV>R zL28hO3a4R;5jzPO6ut%$m+kCzxP3F+_YP5nzwsloe3iG5@8gz~rY`H+uKVc{21{4} z&xsh9%?`5Bad@}Kbz4_9do`i|m}T{id1*^Y4C8E;`{}E=w<`D4`&#^|L^_M|rjuLD zqP(H?AHuRrN@QKJpMDD$_i?hXHTJRJb98OL-bvLu3&rz=&Gu^YX+;|g^{%07L{>Ap`j)J_l^(V=DGnQTgb3u5h@cd_GlJz^C z1=spcF|QaCNkNtz9-H>yI`-TY%d$At-NLENCv)csjkuLbT?9@U1Ip!W?_@OyQtKa) zLGYJ5;TC0mVZ%??%6`@%;}AWnudJuP4IiU7SnSLzbhw+Uq#MK_i6I7kYxEv`_^B22 zv(40v5u=|u{)BdsOzD7?yb7q44_p(GhZvUQ(ZLjgfMrm9D4>uBflj z^JP?o-#l5e25Tp>hCUf5vj&pwVLligkG}(`+Bh$CJXTHn^g`!j%hl8M*eagt4zV^A z*XXI!7Z-Aq+Eu)m-~!W7G5Nx?8Yx1 zu+eHyQX_e^;t8ta(*>j={AP4Ct9dD#%1(b zhLuCRwGSDw&-nEnFq!B&dSb(8MkO>+(-|jg8fr!3EXE*vUb6SL^9Jd&8nkOJ$&Fi0 zGuK}LXOV5>(7m#IoM#2fdV{}G^ zZnBOiquIHbc>4!y*7k+mu!*P?)V_&C8m$^Rdj8QIcaF<(>#ZQXudyOAY z6qU7lk6u3OM!h`qMk5sf^tfu}0wnh?J;B%=;M>+NPGGq-&^l;NF6wtSnASmbmcDP^0{hS zd&SZ}xS$6!De^)l9OgQMg^u8Du4PNht7~d&ZrSY+A9QNyumw?B6=>a5lNWb_p}B6U zn6-~n<}gAFLdy84yY2mWZ9z)dH!rf!$zHX~cfN)ZNl&TQS?Zfq(Qv|aRy6#@v{y8o z45uBXb8ziC4gbHlV4Y?;a!JJ2>S|uK4B3VfW3g5RltZ_?mny3^-IABA>QJG#VLeX& z)!GWu7$3Pyo056On>0EpO^j#o$aw!yv2d6fvoG;VZDw$^+-{zrq zv?FDnNfS{vmCUecVWaUZD_UjNy1E|5$9}CC%+m)Wc3v&Rc@bZLY+S8y`o6~S{$4M` zTlC!cK36Hag-S4g@JA?H9V+3G^JusvdNJL|hH`Rik9w!8%(V|LX!{^ucPNXpp`!UN zhLKHr3XQig{nCyVlty79m-kT0D0O_XsiC46N$Vi3I)dtxW^9z6Ejx;mAM^~)p6Ag}jv~YntB>D*Y+?_&XvV|>r3`j4!LxseNd6>KbxArdtpDY2l z%eBpHA>>lS??^`M{ecPU$P{bLl0npXh~XAmfoV_GaLLqr z9v{*Yt)sxahl42H*GB=Dy(uVA3EuAjOiKx8Sru&?i3gi~adr-_j%tlZ!@j!~^>fq^ zZYW^ocjqb6S+aun8zGl!NH9iILn}i+XX|d&sNL(PbQCyj=nZug#3jlWG;YTbFwDbk zAH;DqX3+wE4=%uqRHVZ?ikyy^Dx(8dC}_pD!%^|k%%mDNqI!$D&|EusUh{_39%Glz zZ_zVv-wJ_Q@7b(XH97_(GH=M6Ff1 zv2K~-5bKs5<;JB_H`zid;_c8Eov!%g;<=b7R9j#R7uegj&Mz-!lj!4| z*Pazu26efm_)6cc?>@@|Wt2(lr3>tP-Onsct*CTA^S$_-*Q!EA&h)^^_2-FdRjDiQ z)Y=KmI_OB9S(|u`);cTijkU;$io->9_2sGZV+tz;bM<}CUSnJRC`4c@=TbW}oDwT8 zM`!s(tg;MP^I7m#gN6!FJ#(_n;QRtkCi_9lAgehNR&K>03=-ocCQmQOY%?wx?AH3Q zysW4c&C1ARCYx7kTE-%dQ;*4cP1)N}O>fs#VM5jDM}IMeC>d+V(vizOSZ6j&5%g=F zp~9Ga5h^#hbxiH}_fl2&GmdJkBG)?G8l6sAgi%%H3$NVR%jt}82=7Gf{WQcj7Y{Yp zp6Vz*ZL2X8bGn*qhdPQ+*%p!$hr(-8@$?=l9xh+1P6s8d+~`N9()MIP&7S$iCuG4n zAPY`rnN;^P#rWHH`OzsA%VGnvh-Dc%t^<@hhf!JgyH&VL%|*48CvQzcwWgxDC#=?mS@EPgs&g#CbPm zree;E0Nz}KZ{bMdEt|eiKcM$YIV-53BC2rQO{k|UJrQHZ2}S_gR;Uw#=wvLgIXf4o zi_)Qa4j+!t!c?LNilwj6mejuCumxkH5&^29^{fDtHTilO;pcq=!h(%kVstp|7^6}w z-+eXWBp2S9)0IDkQ$Ean>TN;G0IO}icxa3 zv%}^`{@&|5XRysyplto1^5F27h5h35(T-s>a%tVgkKenf)O%T}_hRGv6-p#Y2^*L3 z)-ZX6$`m=G9R`Km(2vR{N}ogKRI!KSBxf5rf25qgv$(SdxnfY9+Tf|lYV&@bzf1X> z&Ywp!3Ve^|HV&zSuL1M?h=p@AjTb?_>EcD2CHxrMRG#O^7&{ct+SpdiYg3zfTk^cw zY)8-L{NMs*%+B5PBU0qs5RBb{0tPEC>{Vu8<%M)M^I~2^Y&NIoOU=FRd>cZFcNMvH&kX3==A@$T{{qF>~#)0PgjGL8*{ z(DMf%6fyiAae?W>c#AmT{@>)i3tW^{7dQF<0}eL_6%7*=1JgncLrt8qL1h%pQM>@6 zqN0L`7Yt@ZOBCLLVtksiH+$2vlGHa!Gs_!ZQZB|#Q&dt=R8*>G98*+Yz(nTzul>xx zVEKNX^E>B!-#N!x>^=Kgd+poWx3$+^yACHf#CsRPbVOzu8e4_a1a&pKP5m~ zDIP?EMT@6s543xPi?gV-w0SUX!>N|m3H%t0M|fZromdlk-nGzrFg`%4PCSO~-gual z_hheUDKRySR|?Rv#{7@Gr4QF3ZyGhe@{tfB{ed}vtN}Me2O}%GSy=ZOi-JM- zS-dX)EFLvi37cWOeVCAiDG0>CoP{{h8zx9Z;`qI{L1jh;0>GNbsV5%dg28C19$L&3 zHNM4KM`tx8tIn|1qw?@AhEc4Lk;Gn_7odLu2X-Ghd+`?>`X#}rj&Int^(<1g(2G&% z?RMaE#s|&_vo|?l_-IstIXggtw;v3QOa$YpZCPdxen2>Rh%rt+$Z^54jDv8wB_zkC1BFf#yei@)j!&3@*#i;sYIiE&+qc zGQU9v(^G}JM~-vaC@Q(J8X*{bDW7NI1*+^VGU!BxKi;NwfF=D-*7Ri=V-PClp&7M< zOd%UcD)W8BH##Ccv}j*4bThIAfAGlsFd-dB7*T>Z4!kfT>I3*9BS~3DQdza$(-Q1~ z((Mz*7cA2xmtbu$iWT+I$Ly17GpdKOZW)r0ZJgm5LPoMecmKLAej4ICGzF#JUUwNx z&i29L{*Jl>F}a=Jdg;sRmbB~Z0;EsF086aLgEk&{*E^)$Sm#ofB^@69Slb6ZK&t6M zk)GT+f~+J>>Vr#SY)IkHFlJiA29=eqo!Bz0B;Z(2TbKSDjWl?>1=e|K$f7Z+^vVitP-hu+s8-`9$Xzj-oNn93iknZp1hQ}}(O^5xGd_!^-z{hW$jM10&Zm0G zTVx;R!5(}ML5Gf-&~2`MxTw12)q$$g6Bo9kbTX{pg0xbGsksoO^@cfKm1o~|Xy(Ss z9(lo<0_Z4+7d6F6-Jq%sn&$V*{h1M(51t=04o z($=6>JFvzQTgkE|XSIsbz9IzPLutjSo~ilavDDUth3>?&C%h~x4{>SfNlVKOGig(S z$3e7RhDX~j@{GTN1;Il>Go;$*$wsOu+WUL}@w6LoWf><3LtOkBNh%W*E!7SZ!l4Gj zW_3|iDi|GEQEjQ`QnMN}5rr;HK#gFK04Zp@SbLuqYZ78bV96CHJK&7RQOqi->|m+v zz}bcn`<@c$Y-tu#VZ8CGR6~dzLZX|*7u0|i$3HOsO4S@LUEg`cc`dfiO{SUo*NN7- zIM*_fRvdp1Wa8v2Jd)h-w{wb9oWlxF(=hnEB?aKGSIUbBdDi47I~d+%aI1I=+bL5P!|*7k{mu8T8Lm1P!yGi{q9Fpp_3^vHv; z&rte+JDO}c4>fk$g^;+}+V(W=U_5JOB0B1#qL5;JCF&I&6+BfZD5z(q)(7F1iVf#@ z45ZlLoMt@MNUb2AeX+|v#5w*#4;;MNa?ZC77S3rq?P8o`T85J?H%#~bf-tRplr>L_ z5`=XR+JdvP3{GP68$yQnlxRj#5qirGI0cr90dsAS*DUpe*z36wg}8fFYVr`Ex>#A5k1(m2E@QyZkygw@&x$QFt7WJ1kUtGt7@-J%pvDoXK^yoCaMwH4Au*t3d7 z2LD3BCp(6LT2~Wn6`I zk<%iCV?!yfoA3~)H{xqJ!X0>dc8ZD(C_6=EV>x2IEPs?TKsb%>3D33eFBXWYGwxfB z3|dZ4jmzNAB8%84jgz<>W;mFkTXAUcG^pLCOpA=bQcdkSWg2b{VZ$sw8G(qNcy>yb zIftUCrD)Y3^me90R=uw`WSJrOLK;<&9h&8jWN*!dOU3#PM};Vs5obc?)|U2c>u_sW zV|%uBI1Iv6ahK6i=q-A5RbFoq1B~iR+cB&e*^Zo5h(*zky0BC@gfz&oEu={~G}(QN z*1Bq9@qfh60YlXQvj zSpm&qBnQCILn=0bdAd^b{oT5JJ3JwG*KWPa?J<58+YRqP0w#!J!p9Mb&c@ zg8~UFa(5wVyR}_Nt1Cf5m9Pz}0jO};;%3qlv=#&?p}HE$U)7s#q#t(Ybb|yn?Op=y z03eS7GAfZ(X{M!0S<|7LSdt&vKKX8xd_3BQ#pz?oLFaZk=u4mfTOP=McUvA9x-}PT z|2h{3QMG@n1Z;mGs{H-0D?$3-GVo+2NUg~~Q3+nt(7VwJf-sCS5G`fuHS(*;)A5#= z?vU6bp6pE~=md8`Rwx`z;?AdA1zHfMLEa$a(@&vRWCtW(#%-*6n6OC{Lh*%08Zoex zwzl%%zZ8NMHWSy|2*H}Oq90@J3?W!oVW-+UnvguKxk&Z6RURfWgf}HPOr2s-H&2N$ zuV5J#+`Vb-<3|b(iKukCns7kXq;ZxVP(Q@j?wa3D9ww?ik|58*M>J*{LXYbnc2DU9 zsjIaD>5hhIaheJJ`nMf<(y$9%H=KT@qDHHQTJ%o5IvfTC6a0%bs47W%87ADr&Jbp| z;fJopY+uS`{|3kzxLYGw%A}rkgU-GGVN z+V>2sO2dFH-&uCB>KJmKh8atSb0yqw&~%Ys(@0^;UI8gc|KsL$aQx`}L)%$?9vVPc z3DM1l84|shX<~Z59ni2Cl^uM@m*pF~=GVBombk*c0UoWm;YxRQrPzc%V7(cSwLCRZi_XPDN+ljg^g; zbd?+|1AD@LB#D{5@zHY}zInBM^TszXizwQQ2(*f#Js^@6MbTa)B8HIJi;1EuA++`a z5l>)yoHd=TVxs8F5JdwYSl&z&?bRxZ_OytiJw#Eo7X;AWOcc$8((2V6{v?f_thI(k z&zVc2^R$P-$z9WM8{A3uP5Jp-g?vHaxwPxO&kHzA4?I_xU@s)2!CH?yVS>XA4AW@# zEs1E%uW7Dp)(mFzZG*f;7BW50G|`|q4*63gIG|ZraUHF9#vFx3M<>A#DTrrvd@+B~ zG=c3Rn(?#_>1?NAsX*%O#o8|7f(k9}942%_oG8wZs;wl5?Id-=~cYJbZ)49UI-Hj410n=83t91Ke#WA(PmbdaH<9+!_vz7vMZkU zuvrm)#a4uPYN1*mUSoPz5XM^bE!4qF@4HqrfWjbM)&V8@EisC^43 z(89i9tXpuTc6EfX0PEDK!{u*4V-Y8XJ+QNYthxlpv$#HCcElO2gLu-5Wmj3lD8F^u z=LxSn;o)#al=qN|fP_^7unHQ2{n9kOh0(}bpqW*eMJP~#A(~2!h2;dg5=eK`M)G6b za_qFyjJ(w^=h$lp1)77_O6f(2%wLf&-bp@Is+9($cB4q+z|j$ zxC<0rnB@gB=CRnp+|`xX>Br*1V|E~Bx^7*jS#~qnDRjl|OXD%T7hB?C9q)*@)bv<$ z($sC)%dSABiF*_bfozumGfM|L0qU#e zAJK8Ku?!mO1HBu~WZg*3+aX*F?(Lj}B3d^6An{xW?9egYtcbuuoSxcKOYzQLR}R-( zA<|x?8%dGvwU?}$qgC27dPXoJ07Rij|(h0QcVV3HTEY+hd zRdbf=F1ZCh4;xHj&MP2la?CX)qvh3}hyRUY%gbc%X;5Xdj9K`L z6}0TVCIpMu==ie<_EG+4#U~ag$TEJw7u_vKSq9ZQe!nID*1SGJqte}SmSt9e1`auK zo&l$tgCTi52BfaM5?wRpio=y?;fm9h=sI&bN-4|S23+AEqo|)f2YllPEN-==eI!t$ zma>U!OlX$~;gf*Ay8b4mhNLVh8J`25UR`PVWK2TM!`}=v(?v0y{6>grDV#EEdP`?~ zRx@e5Mmb&+Fka)MGxpSU)){erK{pYAR6&tHhUXM{-nT?Us=Z7ZmLEoHVdNS|Mw}5- zn7K+Y9$~Sq)v{+u2xqLtm-KuuY@&1z-DGcn0t~aC;j0wVgBSDo6+BcX(^hy`DL;be z1ckf{&sOqe!m|k;<7%-GS>z|d3&Qsh0uD#3caaBYq18F?T1eB~C!;OdgJ>0JV;qcD^ECR40 z5QE6JePG0Gx%B5K{mH{0%QA+B7I!QS-Vk_I;iXnp0m$%~S1;|j2YT8j5( zk{#(YyZ!~60EjNU2N@4^czoh9y>dbjIEhrp$SeSx_FUIZ#DjrYpV5gn9*)vT0So=} zwIM?PVHoa3a|K$ODUC5;m1C5}Z2DuGXHJ>TpBJK0kkW8I-CAj^zy=llYv-TsA{4h zjY+M+4QUeg2B~Va9iW=}#c_HOwpN3CU5CFzQAstsS@%e)anU_;)i~-NNwhuq$+%5j zp&vI7;kbh~d7)liUOaB$J0L?LgT!0adUZ7nchSY_u5^pqp)5#Uo!XsOSJMUS$l3ak zPExa~+H_e6r0h6ZS2%QVLR5O2Qx;A$hu1`zx|2K!x_7Cy9JGaDS7Hw}0sGcIW1VIS2gBz_!)ZzD413t_@# zG4M9}VdS=IOJI>0Sk3}#EP>x4Flw8CUs!W^#^=&UqOh5T*CITd{$PPKIjAS0X~u;K zjreFDO27Cz;TB=SHU^gR18|G1KV?qS-Jouok^srWZA|20=8Fh&YJjeS);V2`Y0L-n zST^MgbOXYKFNp+D`kKqZ0PuKcQ~vM~*BRGaK0^M~%)aBwHa-eTmT-v9@IUE}GX&ao zv(9YonCzl3NOfSxMJYXmI(fTIe5Q#pHDt>QOg7l&OR~I7m-zDG&uS#2Cu`|W?w$1= zvs^}x#b(`Mvi1SaoIJ9;gs+HIoZaTG@IR$O%RxFTIc#Q}@=N(#aY}v)WU8ha%f&c_EuT z#i5gYw}h~)*-qveZ0OGFCH#)%n>FwM5GzV8CCUHkHNA8X?bo{L9y(|}v%PR@-qfEt zdUy7thwwe3TFwJ#Xb{GVxyBe{-L)}kCf@U@6B03kK+FY;TlMS1Ju{};^@K_^?2_Q} zrmghZSLImjI_>j@(yW_4thI}vPN87$mnK_S9r=7tLAnLAN9$=ooZkh#-^Bg~y4>}Bq3VJCCv3EP;v zQ22zo@xlkpT`KU*T_Nb0s}bI0?kXXfxodesq^u-7&%B$++k<&YPAYgX?^g0UGVgZs{?U_?$RY1tcy%WRSleH06wOfV zx*Rzy?P+*F1(Ya$tVHf8v4k9EAuFZwp;8tSA>>fV6GYZxLne20v&4Bzq~alW^st0z z#1K!pqo*Zgz8K;qcl5G^goz>Eaz}4V$g5(AkKED65;A~=tn`x)^VGz6F-G}w|Foo=_E3lL8l=#7-ET;QX zdJh7p5$m1Ury@JqHi=*I9Von=@Sz6_>Bw}-l(rp0b{&Q}dU!LEe+c>82vV;MY#196 zzX1>r#doLX=YW zdS^-(VbTChRwppvdKW`06I+l@VS+;s)D?o9i#e)37;~iiWSYeWi4x+wX~MJ55(l|O zQj$oIbP$jds=O1n(qRaNf+7_c(wu2RLJMuHo1#ow>?otX#mqw;!n<8b@UW?H*B^o? z+F8GYV_2wMvWIM!nTR=owl+41l-?_Qdu(C_!MGSf&xF?DU* zWV;kQQV^~7F|(|F4*M#|;>JUCA`O;4#&bSxJm*I|=gD}^qmAc$tUUJ~BCj2jP!o7=Mq?xBC%t0JcNbpx zGvD!EPx2kTL}J8>P-qNUYM6qX-Kb%L`JhQQVr7x)sWX2?&9 zH%;-_B!``w<^?dJEMpI%$kpDm_r8QjY<1h1MjC77C)cXP?BAp8!_1 zt9)b`mr+9MUY_V)c)L{VBjf@VoeOo2zF)x)^<))FUD~o>6RnRx38cYDN`7lc>Y8d& zhGTdT2a|4s9Vqb4Sb|+C?!aoLnAOVOZhxwkCe#WJ$Tj;=E3kD{!tN5G)tb->=+tOq zu?a~aOu85iroN~gjHwt0aQ&Ei>TRI|C5KxpG$b@$?a|Rk3M3_jn}!@P5&)&bKCyCtG)sYzLEJ+yyKS0sbsSqzVu2IY>G5VWMcf&=#s z+fiCbn~5phcadM!dT>7%l=yVZj^AL zFcmv1cKL;BhrtMVK7xdhOmB>nzkwzj=!M%T2J{SmYi83BUkfqSFOcK_x-8Sk% z_V#-GLV}*#fX8$fMlv7iF32)ILz?oTtX{^Gb*kPutgM*6pr}=A8X6(ofd(a25AxWL zAJZI)eZM_lL=#)Bu>6-6^EBai6b0L4#O?yhU_UYh7>YJ=LYtuKTiYO_RTF|LPo(Md zB+X}urdeAf6oD*c<<|Y~AmkL=a85fI<+dB!MwIMV+gOU`n;`!~dq+!AXjL{cU&yD{ zVk???926{VH6TLRIuW0!t5bM{`BQ|@kA4f!gO*4Jd+)gcXmX(of{Y~M zMEq`oBYw4IX8%Ci`(p|>owMwD$cmKwB-8u{QWp|>Cv43Ci*y9%xGgwleC{{xr@bhtK6P;_GaKo^u}wd&(Q z*#V}XVB8Gt1k-Z3R8cQ<_=T82V7kZpa2jDXQA|k~)J?UZUgBGZ%@52{X+}}=qcLcK2wR+PJ@<;1lUxQ?mm!MiK!>mwu z(`;_j$Hut@MoOs=|0Aj%rSnE1Nnf_HGITSZ4)-m9k$;+-UJyF8k{4uDRts0^osd^w zZ9T3Y%QA3+Mm^=WSt}6H%yvmt;Uk7gau~x{B+^oLbZGEow?uh+Q6<>m7O;MlpM74W z?7(UXjG?9fmWFbjZAyQ{1!IvA1{VRE(QvWk(mYQtROWk;3uXC{Y2zhnybJ7P`>pSk zb|XEl%r2{wsbBlhf25V!n}oC&$vTsJ+n2OHX_<6Q7w0FGM06q5Mqe(EOqe6-HVG6{ z?SrP)-51+$;dPf7gC}&GVRGT!_h5Wy2U)GGO1hd6k)&;yK{E#CQ`+4BlR7ff+Wj2# zEFFf41Oi2Rw&zN@XtQ<3&4|sUFq)IcC?H7dv9iA~?}_O3sBer}w$UM+nTL55+J4%e z;0sLGQlZ;(w74LhP+V5D*g}zGhJvCdvIonV|GtbgAbPEn9e{|QLN+1<{bwBXDmCaX zFk4oq`N<#3WTr#5LL+ukMfzJ>*nos^P&oEN`wE*X=8zT2)GtWurm0R(^`H`^oSzeI zT+;_?#%=6-0PKTQt$Rt`?E#d_gP|_d_^R~l)MR)8nGbc+t84gBd)YxQ{U)hhq?^o2 z7`m_Vh}7fWr%FhFWS0lV?+1Hvc|o%?YqajcxOlLp9t^qz%h13)Lu$>=oeB0kXBa=k zZ#=loMHpb{B(-A4jvf5aQ0!|b!Q3&Qzgc&qw?hG4r9PW}qc^laX!KFluXdcEE2|l8 zSd&?k&>Pkf{mX*S*I>Du*}-DJSyhjN=JPii&t*=}tT8$2fXHd3EE5k*%lV?s3B99y z&oavCzY^Wmj+1n!YsQj<)BiMVxSYRXn3!3^4|ceZOn%DYH*mkWxt5@U5t_c#S^EG{-oK#O)NOezeh@!mv zmjvcL*vYIQ+KtH$L8sh5j_W;jU{Dy4#AX_hlH#c6yJZYHyX$>F9pN4J?L|bL&?;xkH z+IoE;#+viLf(?-)*c_~1bDpnDu*X$fsJYGbKP@j`gPPE5KBNj=_+bq2`Bxi$zJM0y*BEMW&E~Yo&GagOYihlo0#l*o-+cZzD@&)=uPOg~ zEDhZVVpmqL=WoJld}CFQQVf8oQP(QoJq+1)jjqu>490REdy?>4JPx7nWOBh90a`~= zI_o~SO+D;?$rw5hS^WRs7&;rJrZJRC|NpWv^uIOO|2M|ag=m!jEyvIq#5L}ez5l(( zP%)oNkx$z(lz#v3Jcd%e{>2y?kKn&QhOTK75MxD3i+tQ*RAu3~aBN^{q+YcF3nG2= zJ9_OVee^zkbdElHyFPlWK6;BjdXGLD*N^u32QK@hD3cnhFf2fW*nUMP@3X|<=h0* z6<+PfJM;RZm?U`T5wQ23;232p#`a1l_-lGXL&{wzKzW77w9TJ3?S?8uvFaUKQk%Ze z#lC|ZzEP&ljHX_j1F|c>dXk_dL1Oww;jihh7^v|ZQK&hj7$bX^jP58@YdsVTWbX!$ zKUVf$f4B)wrt}F3u1pujnp4?ZQ!&#%K~|PA9f2bt`HrKH;k%4c^`dsdga zuY0nKS+(!Q!mJL^{Wh!ipe{xfrr!7yooK{I_VmbJrg0vAATANoYqx8khkREp#?&;J zyg>P9M%mR$+4?oL)^y~>LPSwG%idlNA_)@XXV{e(Cba0)yR0Qi>5$-Td>g@*>h(eO z!Zre`S58r+MtX`;r`}{v=n!QLhCiW$F%gblyVc~t@~?R~V6Z~EGIxThzm@39og)fO zKj>0@pg17XHB2xgQB47;e~%X;Q*)qWxmGjv;wmtm}@_`z$GSksYhU9=bgJVVEamBFB1rb$EEGumbdO!2GOPC?oyloRP6NXPCm`(D$Lv>hK_p(aCGZ?J znnB^4QtcZn9aMXQ!nbN298_LG;oG$i{wnX0l$Pwh=a9RRdthBo_Rb)94+Ui56vQ}B zui6ER4jD!;d8&J3<)ICF?5|b3@FghR6XLzRIKApbQ1~uc25g_hyf?4T2t3EDcIBt; za?s^Z*VS~;t22ngr}#{-6Xf%iY@;6+
ne_%+>#Rku;K5U52l^uM|g_LMeWfgiA z9uKMJRj2uThiN|<2+@ddS^BTkJC0L;!4vze4YGsh;vmG-^#S!b`5Bqc3!dYTkJGP< zvbSCE>)3H6{ko8X?UP)i4p*Fek8V_*LUpdwb`8>&Xgz|oC$z4tP^XP1 zFg?3NI=XR;l;J!Rlq}J94hqzE)N4=awIzD(2_u~?VvI4QLXj=Uk$Spn6R*y3$U}2w zmad&@2yr~2S8X?pk?K`jdHk>5E<5OqeX=eVOz~|#-bFJEv6J7!Hl>cXDf>VVQciS} zlxB@X9Bl2Yw%hBLZM8S6x9C#0aO;kY8)sH+GOKfl`PRLkUSOYxd}f|o`wE|0ooQa> z&uc58-E%g!0`__M(+&-;b@|5LIIDEcPcL9M7qnEhh_UW8{ZWgd@TQLD3mPkB2kRUz zG^i@<$YRnS(x8UImb&unvg-Vr-e>Q+LYKWF|9bDUf@}UH_QXqt_H2-LkH#@hr>?ML zZOfO$1*t1iu-~mnzfP6{(;sqab{t;!OTA#m-JIA9DB&d>N$6rPafc{Rz`v^P0A9K} z+SD=5th#D~#?vJlTQ1~MYsbmUlYF7iUm6#L?xre%6&N(+cyaxW`yOfLb$azFlN<`M z7hJFUR4&S4?k_{g?5Fy#l}2cYzY_I7uB5RND+0hC&1FDbg8>IS*C)- zpsG`{gX$B!wulce%NIOMFnY2PLJ2%P5!k@8bC@CrmLeFO#F=F9P_qS=(v<_cyPoB$ zdM8dVi_?#D;Z+;;DfaqEyeD9}O(elpi|Ckq#uvr)PPLDW-4Pydj+L<%@GZfM+^9Fqctxu6Q$?z?fOCNJ zfC|9RfD3?&fJ#6W;L@Wa)nz57AS#Pqy&(?UWT&Dr_5)24{Pm$nrc&#`C)$@F_4bE| zx?doAUkOe;TT1-gB|dTbE?Hyji^e$E6^)SuWKDCVORk8Bc0MjTBq#?NlU-STJLo~^hT%Z#t%ei3f4^HqyWJ=73i znMhbFco`&PmgK1o8B(|3kKWF2g6cCkQFgpC4ni+BP&Qs>L*+j3*)6^HSAFUY>isY| zy9NA_>YhuZCUAs#dKC-KM6gb^WjcRScfCXYBZo|w|6PPIrcJp8=DgKM579^$7bH#U z#Mc>8Pwd!%ksae?kzRFFb}$TftS}8>d#lF-t@K>WE&hJsJ#l!{YjclLh5MfNy2@IzjD<4YHh7MS<7A8M?GNdfI8L^tc#tIs0hd{EUBq}Eyg)-G?m>-f zgb@=s9P!Sr?AsDu>~_u|agi5baLlK{kxt?< zbZp17o@{V*(xC_HmTkh|xJQ?|2ZJN8Iy!c&S(Rf}=jl@OxOMNQ7mMSgd9A!rMXJ+j z+JO-1K)!P}wvI1%$iv|1iov8F$H@7&dOPH~7FaHLshZ+4&FjkOk6H|Z7h_~Gjgff{ zO${)sL}TPGi1Vm#gx8;4)o39XagG~8(PQ6KiC-g$2c}d{y}3Tp2;?=?pr!olk6X)*tu| z#z_GO@KSXavqf6ge|bt$hg3&uDsGzJkiue$G= znv3ze292Uu-9RhoRlmmRQ*W_HRZx_MxFBsVMs1rB8}el1Y~&sTy1Yc&bF7syyFeXR z+mZBhok8)I@e*Upa;+CIDjDnIV};f^NL4P&z)=v6t8(!8iIq21Ik+`I6ZbAm+!LU9 ztykw_`mW*CSel^IJL_VPV#+S#BbyE0F7iv@$|~Z@qas%x<@9*jflb-Va_xhI&FWn= zr>x7P3A>dcH>Veg4B0>vHcqNAVgD67f){DdE=Vt8b2c$!15MZsU`7@MFPO1NWX3ux zGwvZ~OtoRgyRHvynGs?zkr~Aa`~L!F9QzbztZSXHw?CB;*@S)HRlEJq44}OwPS}^( zgk9Ty!mh!DjeEOZc6>P2RQvc;&p5rk=H*QesLyr&w0^UnVrJ zu2@{5&(J`TZ&n}05jnD=twdwI+;}zpS2N+n*M9n2q=7(4^? z;YVRcQX(%;wj1T3K1BmyscV^G2;T0l;k8HgG(31YG^FJRz+|b=+qEvsbqux};x?|f zNM*v#0k?zAudR1@O))gJBRY^NBuyTqbuMxUcugLimwX>=u&!;6(^FcNd@ zWY!FaB3Ro%{lesjWnFYTm)1pT@&K*lYv@@G6tgP%CoD4bFj|N4CN3y^Ls2j_XF*F@ z+70)#0-vlf`y#u5qF}V=yNxs=G!%Mh?1CE#rLZPcB55d;kSlE{v?tdCPYsjn(^$xH zcxeh=d;a8MGIQr!7I6$mnw-WLi&b=JO*i>zjjOy&+r^#KGE8pnh=2`_J10RKourkg z174s4GO)Eyu0rjP^JVNvv3Zxo)*TRMZ31NX& zLxDZ{KpYRcTVgV!e2oPxkM^#`eAzLU#nYPJ@-xWTNo4FaWo(|9v0yP{KG?P)C5O4b zXXnhKN9Z{_O*iJ+Yh2`KwK8|A#6n$3aG`rJ`7A3+(&qo93ibt~n*z_V8cOh(Db`#W zYL05M3^nONu6;wH54mQe3X!T2K6{H% zMBQn-uNad$rJtr2;7g7WFZiC+yoeh00kSvTV7P8ja_j~qG5@D6^?#ZoA15C0Er$I_ zjrYJjEEq`~70j^F7$_}Ba}H<|a_z|wXSuIR+IY_Qf@?X}dUz4axCdW^ZkUO~uz(Vh zATEkRX|TAe4?LGqO68deLzZHJ%E+drSfVlsyke2c?BS)xCZ1vzGcr$G`HIi?EhJX* z!Dlo_Fe?tO@>`n21ujUV-(B!Mqca9;dZrsK#V}Gaz*4Ljn5 zUC10}$wkzQrTdpse_SS(Ipp^!boMK8@s$i#`!K?{FA@Kr& zUSmNjyqHl8kpb!rdMTucmCE>^CGhHkBp zP>#5mqz$oj(MN2v2j5YfS=6YZM;{q64VR%^OEqd}-edSXIBM_A13sje|GZ1>`VN|Y zP{H?w<}}O!jrc9eX~fMGd;4EU6vI~tU(pC`%ydRO?b*Q65j7fT2w2SKB>ToHK7ZDn zxvgeQyxQ>wbgUa9VMcLMFt+{y`V|uW3Mo`WWN(cnZt&n|;EhElW!OQcGI|>noeiEn zT+i~MQvLxgMoL{zV<>}p``FtYe+iZ{97<_9a*~g(b7;U)<)T5+3v^*LBNUJEV8!u> zR?fGHW1zD+JSh6M=2@stw4KDm_WKG6wCp9L5Cad9VtZxq#v`)wDn!17l?)UMXGm~u z%fTE>3Ke#tumgXaGq@@Fi?mcy^l<%y4-<1|@W%2;>Uvc#)vuE1XTY#VXTy+A*xE3$ z+x^y@=u&T^@EUK!WLh(w!J6rzxMqSa5PC{-4C0#URY>SV;ECn8iG`tx`#fduZ2m0| zJ<{{w|G>*O`FA~B&*b0mNLLAUSQ0W@B0(#pnxBtwX}D_*%Yp%X0KZCt@3g!pF&%1E zAApq?HjgMUm4TLG)Dof6%#)gOSS}G@WCX8nT9!*ce9O4TFxot;(6HSPHOUzk`eFIH z9+sS^@s%*l14|sz#sZA}oTlq~7u@H-#j7(JrJ5;Xpcd=WNWL)trbh%8s4mCNEiG&L ze7-U8q(hy@rUlKgL$=Sj0WOuvFxriuuq&`cIJCRPoSQWk7j`3dwwMiua?C}>1j07#BJW(A z2#B7j2g1UT( zvHV@&lh@0bxxwNcV4NBLSPUI*oD45!HRHH+zhegTh)ZG0KN+!aK1 zRU1{R(k#>v+4XAcqqVH&R@m0u1Odc05sB?YVyJ~g_B$4SC0FEEZySF7A>|3yr|O(a zR4R$e-G4t(ov44Qv1tzSqrOcn_~~>oo3$y3F}hJ)x7QGNFN;ejD%9VgBUH`mqb5uU zwIoVq+cnjOKn)1|42H}NCIU%BAbX=F|Ky7K$Ns3bzdc_07y17uk@600 zL@8Y;T4w7?TOx+H$vnGMi8~63WBvAec!9*m$5;q?Ji$lFwD9Z%5VC)C2{LKMr1;+LREGuxoTwt}!3?KiM#ZZn}|00rHM>a%jAP1dMB z^9ifJ8d!5EYe3omB+6%mGM!N5l$N0$wPal932f^awp6S)Eg_~6VrNF{sBy6^Et+Ph z63Q+@xw}ow_sW7N^8FH_R1(T5ptN;=%D*muo>5z26M>4*0#3}8OhSZD+C?xJW~17S zKX;)_Z=p<=!P}Z?jhN{?ianfSN4Ja3>Pwd|HO9_DdX%)Eai-N9VtlFR6BW6N=xB&e zSI{AgjEMUJivX{mv6s~wVtn9j6PNfyL2>s`+^R1SS9Lo~NCcnTFdAWXBdlt|+6ydd z^Rk)98V(%WMz2$B^!gs*ZM;w8&Lv{a2~=C<@a1|;29;%uiqx1vRBYMx8$wYK$^?e8 z$ru9^gJB_6X9RgM+D>9YbPK^ah6Uvs<#2iS$b-#f6buZOsh;@SnyK|e5RBZ6X8EG& zVK^l^j}rYkn@U$61Z1K}F0fQ1c#v*IJPEm16T= zCr)JZ{6+Y3_fY~GmO!Lhy6zy4xg0VaDZ_VKZ8j?p7%2GnPwv}3bW0*j_D5{VaEv6Y% z0b7hW;X=F_Cd_1?tOVB6{T|S0A%0`j>fy`XL)6{}HG?|Om}4Qam0ZINs<00yQgyPn zTn{gwNgW}K^&%u|$e^0c_5jJuA?(91V7oR>T<;^+tDYrF6XQBcw1N`#wj>%z`L#0C zR-nvoMV?B?!>0iG?&s|~w>Uo0yceE{*wo*=j4p3myaSBaUbCq=;$taM(h#K`7D_aK z=0@5iT?e%5;NaY?gtqp{1PMRO7M~{B?+E`C;ZJ%JKfA^=%0a3~$N&&W%!~)Rdk<;ag zW{RO0w<$);r>!Nm;H$7;c^e%7>C;|ejp((eN5hsc#rBzo*m+OJrt$fdF2BF=KkndF z+eml7hPe|d65lRTwzs8z$!%Z1M<~iFiZY`uO7;K?KDq7jdBWdL`2B706&8GQ+vCq7 z{Bpu?!bD_gZ>q0&$UIv!Pi#GyFq;YUbQ`7^f!1`Dp)>$i8q49f#>+#zhv2*1fa!?$ zFKax)&#}d$-g=hsW)t3WE1o4gB0nrz$oN530yDUx*IKnSeSbi)H&E<=Cu5&Fl^tR! zKe>NiPkyuX3D%?r9!&&K5W#Dov{sC@ejr<<^{p2lUe4CHVAuG+BJvo#m|I6gKDH&o ztFpp`e&{*iFJ}EMOz6&j8Pqk#_r_60mKfiLYpuxjv@S!Yz9D);!a;9>Ej@#QCN1Mo zn<`z8%a#=5O^Pv(VtBR1VEyZv1!8?-ui_?pt@U{V@y1ZRjTEou<0p%MDtn@(KFMw4 zC)(e;QoKBhm(vz6d%6Xm-1hjF!KJyk34c`^zCrD0%$iD5jMSJ0*Rt;zs<-L%G$ejT zk^4s=vb-%a+K5+|Q2$enMGca7h;amYt>vQ~<^qa3o1${MwLeAEP_&%3Xl%{d-?%@7>IZAiA;z!CYpoxu*Yn`c+#HIxqAi}a zezMnC(j&KhdY@3d3W_(pEnaqp1)tpZ_)7?%n*n^O4gNb8d~#7g6|jdKUSp8Fk6Nyr zA{gSIsAa03=ZMe{B6R$tC+o+cK4Fw*p@gbDn-y>#TWr?7{kUzhIf1%bB^WR_o+xQ8 zl(LUn@YsoLUZHZBSAAtpPeWHNB3HaG=25})l zZhORYggB896Wa(|=(BxCBRH#VwKsv7<}-@3isH!I#i9BTirR`XVH1#FC*gVo}G+Z6>S&U_m}oVXRc!q({|kM>zdw0_QWrvHeHG z{Hma~#liYjVl|%zOXg-#lqKz=7}R@=t3cl(8Cb@={i(6$+oZZ4SEy;o&mt-nM5V8V z3eD%sF~L}ym2J0T2rYCL&{{S=kw3z(9PtGHV8YiB{^>vATYEAI0GtW$6yg2bikDsc zzS!*KwlzC#9WR56bDIcz6|gDcAF;A(%_yPd5{ln!po9a3))-4C+SE18{vQ&`JVJSy zs93W@vEN{y=Hk;c*6h&x6H}`0RC)W^{yh|r#jx-`_JZx+E~R$+Yy35YPy5fmiNBTb z2mgKiql9nw_wn%pCMVGT^Ka&713Iga{rB;=5dQ0b8{f8WpXNX0fpI|ibp7M@d1m!3 zJkdT@8viZ)5DZ;$g8DD$9V!9q31eon+WG7DOe2iwN{)k@eD=qEmO}7NJ(i>w5Xr-qidIK%=V7CfCvtTUk z5P6Izv9^L(_W${R8)GHhF2D)E9Y6!1W1NJ07BC1f8ZZa22CxC}1zz2H>B7 zt$^Kt6M(CL27t$6qz4EAOa~+YG5{L@9|Qgk$OV)DssXrD#dQYs0t^C#0Hy;L0#*XD z03QRs1{?;I0j&S(O2=?MWiVR;NCWHv)BrqAj^Tm<8vr$cI)Kk9-~rMAdjK_nfS<-# zNpa^6j^<1iqq#fRM|0KP#&A6+!epS?Ck9bZO#(7|r6u$4zn zdEDYf%s;}XZ?X%=OlmXW`MijTRPm^~O50F-comnuWJ zJ-)%*(j{%>eOfsX&+;$rIC-9iN9FCi(5LT0;2@uU<3ukDOZM%XJhyKg{DcDt2-ME) zyAc0#+->9~SP{$(2@c^lsDimQaP#2)w{-qnKAsjYLOm*M?#qJ$C~gY1&Ge}%Rlr~_ zZ1OZ83L8Cn26HD(4pGtX=~KtE%9$2E8dn!Mj>^~eFCh2?@)?l&^nALF3gK$r4Yow7 zLA~Q&^XGXMH`vN2hTr#ZZ7kaJ>eKQ)w{O5JtWHs96n8FQ5VbnomjGaccJ)bhi(s_D zOMR1pNZ(_qZCITzp4)e^7~9vEa9l(@3oUCH(WUZ|YxPt81)#n}_hoL})G!}>=EhG7 znL%!ZYU*@yCyt*IPHx}00qlRYd#i`Sr=woD{9y7z*C8$#f0Vcd0S;Za4k5}d_+EY` zn5%^wa5b14Fgk>r2iNkCJZZM@w0iqL8V;KHSEu~pmA8hH?`iSv@y!81*Dr9rg>wav z(IPUo-vxk2w7H&u-T=B3^#TBvCs{obVL4zVfJUBi02){(1Ev9@05O1Az#_mBz%sz= z0ID1vKo8&n9|ArCd-AUkVE0QrDYz)yfP0JEWljAGQjJAWIzgl2fPRP z2#^i<3h)hJFW?ZM7;qAB7H|=84e$%#9^gNKM}WtG4ieNCKnCaz=mF>p=m!`Gz*NSK z0jL1u0h0mYfM~!10H$zm9UvXR13mzJ3fKnt3h*7^2S7fc81NI|4B%(Lb$|)*7+?lC zI3h0qS3oB~SHLrX9)Ny;7XU8-rT`)V(STS$3LqWu9^eDOhk(t1&jDWob^^Wu>;)VL zlmboy&H&B=eg<3y{04Xccm(Kx3+e8FPJm|sy#c-ef51zCk$_Qvae(mvHDDSb954$I z3s?v13h0nBAg1G;!&96$ zcR#VL!+Z4!D~9e^VBGfM!p~mLy4-PlZuRP3#-D4ls?L4nKk`29h)qkoG_8hLi-u7IlNM{rlCq)oY4(k-U^ z`2PBReSA;sjoAF*;WM%wKjeOvYu{g*x;rn*87yMd3WyzBHF-yHG17b5Lar5v0{-M*-H+R_e$gh|FBl3jo zKSfo0V#ACFJKxGZ#;?gb)O@YymHFcbUh4W_&G~m?CssU~5%azJ^pyQ0G~Cf`Hv*1S zjM{N+!o?3OM=m>YcKf6H3+EGzi^nuqEgv#AYtc95x$`b150r%b($gVu?nIZbOV_wx zQM~RL_VpTen{)Z@vks{tAIR#?ZIiwof8VZGOM%nk z=*anvCl|%0y*_Md_urhBEMM89qNT?Fynf~zmpo2QxUwkm+M$OJ?;d-1%&~*d{QT}7 z7&X6eVeJQJvriOM4xf7e+T?qSj+|W-dGy~`oc1eU8}@zZC4cwIi9KAtZJ6LNY~CA^ zQH6KsT?@aqDCh3G%LlJMws`D2dt**MtBX6j^;}}#VK?HZewgBR%3+-Akwe|=pL^+f z$M9qF!$0=(+pqtUUz_KY9NCg4!?Dqfe&EY)`xP9{OxqrGJ`}voHcdOU* zxpvvL;@tVSM&GEo*R=Oa{Bqr;-amCamOktGLk-tc_9Ui^JLvW6Olj7N1ev)^?i4rM z)vlBIv)K0*@1Eau-n=A6b!KU|RX1F=-Z|%fak@@2sbH@|P|Wj-zHIC^uUtKD@%YOr z%U_+4aCUd~%nMa5uw22Va(zDgnpE-w%}*_xRKD6}B{Hd2Ii-3{ggCt@Skgae*P&kqqh^ z@bW^R`LWnPVe?@V#!X7}nYKDv6T580h-GX)=d%D#vd^-Zg|R-XV>N@sjB}QcD`J!4 z5|ft2EMGwTvY~?p$Mx;&qZkRQ^O2Lk`TJEux6l=xsNfYzv6k&*>_VU9_?RR(^R;nt zu}R64(88DcF7#Pt6Ypu|C3<=0Yr#+ZZc}wsZQSC-l4D1Vh)s-}k3DE|tfqZ< zT+HI7Z6Dh3kwRNAj9P|pVJ)M$06-r6E6k$*Z{)+;gnw#7k1-+Kd$UG!^8vHrueA7g z!QXGT7@n+2TD*Lbk0vqEXKCW{Mcm@$D`S=}Miq+TD-x3zvkiJn{Alh|3oJ-pR)gha z>pv`)I3LFkx?2O9LI0J6(OgJK2)7!0W!f)?FJH1eF=e?=?5YK^E5t27w=H`#j(I}3 z-Jgp%R94&Xs^tq37siGqE?%yQO#<=PI2AXQn}oj;xj^n^ZV(p&-$a&dNNjuDu}hQ3 zCdI~baHqv;B4UsloSdh$xPaivQIKs#sJZz$hzK2g5KZdrq z{ki3wmRpMdSkrU;mur_U6}=pmB2ILj$%Aun;+*U~Br284k^T)0;KGPVf1lxDGdf7Q zR{{be!?39E@xj$2+?tvfKM(&nZqzpIoeeKmgl-Qv|T*TD!1O zaMR4@aihj3hb1L0h)qsTOd1;-qtPbCh9$)&$1W!(d`&fVl4@e$%M@wu^4L|Hm^fCE zbC)JAqW&{?^>V;qKmZq)6uXM{#&OFM7c%_#)hiM~WbT5P`N;@ax={R%&vEoUP7LPa zmL?`r+boD(yp+Nq)FHKXhs3hZe;5`QnnS^wnT&hVkz%ZTaxeLv*-Jd7@`iu;|uV zzKg%w{~bO?{5^ckjO;5nPyJD=;0FKVa`d@9%4hoh=dEV>j|#5v+vl&$-=o|-px2T` z&36=BAFm1KFZL);{3CYy;5*k9+^2(AKX-GF@(+(U-f4d3HwD+zBX_LtcghGux6cb= zZYwyy5|^b5zEiqy`=Dag_caRc+;Z(dw|%Ev@bk){rtbLtOZVnOH@{N`eDt{cq-XK_ z*tIWi_Q|}Y=3iXqw(xu9JBz-Z(ya*Tt?`O^W&8I^!Fc$+qdlq>T+ETQ z1-0KR-2+@h=WaDBIFG9G4Ssu-(cwLPl(G^9H=GYYzHqN{O={|cZOWe&+|b*d?{43# zTOGO(kflqeEIOcUko$iYUV!=yly!dp%LB^l@-5EGhX11A zj{Ncbx!(>bP47O~wDaL91$S!NZqNP)mCt%cRgJu+QE(%Icg=`Ds2otcJb1{w-xb`R zU;RGIIjFpR*8A=~N6$S-Pha^TR!;iI;`wicq5c2)`DfhH!^%C)K0bYCfL@GK&!}C8mC?bs56?~A zqTm{qPuzR^u=3H-Egz3_KC0l#+y=`A9#O_r8`ov`M}EUS&n#VbM7emn^Y6;{!C#$@ zym;!HBg%-IXI{Mc#{mV*(uWSbb42+~H^YosWA`aIr+ohngN`a^yzA3-$#USUHdNIw zKdQVu{j2^4f7Ex;)$m#09#vk@_o#5%g8tI)x9x>@k17+ieTL+Ii2Qf^rEFlp56TPA z#5Bveo#6d{^hOX>u)Hy-TQZS`0fYg+x7=Gy;*Gn|2e*%a_BOSI>QaOj&H)dEs0> z+B4tgu6*OmFFH5BQl;Q#8UFpM=D5-^V&JI772vPJ zUwRzfcU;+F-uEHX=Ocf;+&_~4=eTlOr_Zwn>A`Q)ou-;!%u~Mb-P9AmZa%NzUao1% zSdyn4u&Zxn6_4^JwVds^D^KY;ZH%YV<%)s}{p`+`+j+{Fs}`M#`=vp_)j7?3X<)um z+Sru!z!&X%RsTxSvV3K6ic|V7cktJ*|9C5AcfNA&b2Ve~T9E$I8FTFJ<}2U*c1y71 zR}U53hBwQ1yi}m{%Ng!w03Zn|0vtw~XH${!v-DDt2s1Bk120zWe;qkIIU156#mr zfj>TdF!&=ykuu^}=SykbQ6G1VZ*EL2QttTpmjK-^j4$8z{NkfyMartO$1%Y=)Q98U z16$2S%71$Y?D*%u@)g|HQ>VTSE>>oHy8kw~C(^$W*l;4fSecPCDCXI4(C_n|s-~b= z`RVu%bF%6&KApYxlbxhQ`S3!q^TC^E6K&1HItg8S;^C&kiI<iMV(-0S$A-OkMS~p`6?;ciR8%0ix-Pc$|Gbk43|S%G z@4I`y-~V0?JbCAwx14j{Q)ZIPyy!{eV27Q z82D;*-3fnU|E_Xz&eF@Qd0gr8%T8jv_x6}p@!n;!$Uo~rT5iLAEAvNKVAQC}Iq zvP~sdnB%_o3yVF){Es&u`^@(WbJ%6OdymBzTkh4Ei)%MrVU7E~+1k4c&QC%2O37Ya zVI6xHeK@li=HrWyK{gGpvZCwea?bZ*KPe`$nEWd1^6ifK{ySJ7Daj!(wq0eChYzkU z561Ym+dtrP`c?M2_^h$1gD+tJj@x+D>KdEWF{J9S9ayhcd%X83ud(JHS^JltLjRBS zUAKGRHCBDmnm1<@@ZbAoza9Q?jfGf6?0ZxZ{CX{l22@L8tEXm{KQRU$Ik%MT%yvm) zWiOBSs(r4g9p`6sweGwmHYdxds&r^^JFaHQGQQW7SeF-Nj5m%(e)^#Ed&*yDMoVK> zx1LtYjthCvt-RND)@|;4$v(d#c3gv&AErlNXUz`I4^Qrh{*20~TJGU>=KIzs@y=b$ zmkr*Pch|VVYWY4czDrijj$5Mc?BjETm2397%CAGHzPd*BH{4)LT6qL{wuF42sT;VL zH<oc<~Z?b2}mG+J7hxr-*sKUqLH<>b}U+K42zu0lHkuha=-(*wT z?r#u10qd{3YL4UYH`%bS6Ao1N$2{GHU=X@%o$c5ZEnM?1W6z0+#T zy#CW}vxIdsh8JlB`I*V~(#(6kEPyeqTGff0NOD z_HN$NrY0L7;(Rx6YkKGV?BbHy+n+7TfMpd!DprIxai`=n{9Z&+O=F!KuTsP2)O^eqd+x5jA`<(7`;&<&vd7GIP}B4z8LkH` zwiplC`IxnMzUIx&Ke3-ZJwEx{hsSKyhhF_dQsMvL^wsbUGuk`le9wo8$t>gYgNT~b(f|E*Ygtr$!e#}JA3ft9*4yHSlITHC*yf4L zUk0ATd{;O4t4-_^7C9&|zG@jGtdD*}O*K#0FUcO){Yzv2^BY(6d$kl+Z23Wp2iw8# zuufvH9fE7)j@rJLa2WK+5lfp0S#V7Ux#U z&F#2R&GrXud&W*?*Er%h3GG{9d9ml8&zNdrT=Ue&l%LYlZ#}^1mFL|1t>e=_D^&?&)*ZH`cDg(3{A+E&i>fbt>yuti$VfFW~_nn8oio98Q z>%>bI;N+fsq(eE3zv6IgxmV1uN~7?)8SqEM40~zdEB42fYR8k3vEKU!Id47riWPYm z;`UYw{+21mx{?&l_QN0b77nj+A&vF#;3V{IgyMRxWzO{umrm*}ntUqj7_>)!x5hB~%BRg+7Hpzh1-CddsHBFC{&0 zj{UF5}ze9M|m-G1n9*_w9Tn7FX8D(TG2tNtIA#>3wa>Lv~UEu9TmZWdF#D%R`D zXQm%g)7eOe8l}E$zHQ63{y4p^YX zolJIP@ACETsaQ`F_mHHOpf0-%pMBI-;Q+_j-27Kt&cyZun)>3(xxa zO0|ve@7s_!pIXtS2-epfHn#QKEcR{Bl-0*I8di6nQ~!3L=k7cxe=t+SqNg;wWChx> zb;EJ785-6^va3mT(8ZND-kX=MVXkwsqKrTf&5fux;;n|QJtsMz{6@o?MO^Xg2AVM4 z@5}zz8kV6tGp`z`W&fMCCZuUt`rGjBsc83@aWic?gI@gl$AL{RHO%{cw2cX9$Elv% z2fxs;)2iaNj-+bXgc{Lv%7C^EPx%<|T*K!6a=QPKXRv2p{b+H}KF(Ll_Is*f6{;Kv zh)vP3dt-L(efLDe#+t3jZVy^1%cI@IWDQIHb|mb=V+}K2wrO(-&^gEcxYhlUhB2cl zUuHhkFvV)CY6%ZC>~8-nElfb?t?AIo_P&N)8sgD2?4E|5?UvbV%UumyIQoUl!#f&g zsxB)n2|6aSd*cqbHSElWVWk6aX_)3(=hq8wYFJat!^e-`(6IHv3#UB0u3^$|yE+#G zU3>1?Uk#Hq?53N^u5Q;f%u)TqLw;4m#wQHUnsPX=D z>M@a?S$RyuHr_O?G5&~#wQ1c-+W(M-rLL&oxak268?~&#qd)gz9y}f2>)37$d(=fa zBYdZZz1wCpvHo_n=i{e#Nn13`p~~;OM#N%1d}mKeY}Bxk(~T~!T&H0>Cb|x@SgT>L zVp^QqxC(Z|;x1QTpTFn{7?Z$4=9*q(`fQ_D+Ue)S=|ni-zlcG%WGg@_)()Y1sbBT<3=UHEfoRSNRk#4U2s`WZ+y6^p}mR+0sqJp51%s zb=?K?!u*8s5N8cjnS0dwy%Xl6`odO~gN8LfV7oS}qlT@vy!_R#1I9OFk~*=ChD{$7 zlG?PThLv`k6FAix{wR67>zyVVw!D3-i8UH(nDhNbWe3*7_%^xvenD*wd$Z?AJ#`HY z>ruMa#^+Tu%);#K@b48hEGon|vRpY0YgA#&#ppcVwp=BtnNG6il7r2 ztX9*`w>Rv`VDFtgzwh0U!LIiC{CwHc4A!XBI@jJaGFam1ZAIRU$zWwt6}Nf^XRs2z znofxJ$zUD7R=Kg)J%f2Iahko(DT9UdSrs<4bq4GG?o~Gv%M4bzqxxoel?-N+IQi=F z5*chlbMMc0zoavZMm7~MrsI4Owd~>C$LXxc@w;XXucosV3!ix{JDJWD7F~Y3zbl>H zf7`gVW=%SK7v8z$y}9YkJn=@8#W>F#+%)q>o#1p<(RS6HNrTea*e5Y*hg_i7deNcd z9nx9rM(5HOG)iYD#@=q#4(F*$CY##tEtbx@PVK(_(;shHSeugN%B8+#?=Cwx{e1l` zn`kk5$zJtameFqD+_VjE+1xuF$6EdNmKAx{biuYhZ`u681H<}Rzh&*+l^fcay=6h` z{6^b9dBeJVZrLF0;2Y+ABXUQ=%r~r_@wUfy-fx(uh~vPkHg8x$&n=5pMc%MGL8p#c z-F?k|{mb?Iht03q%xSNJPmg-dx_95wU}5LiY{Gj*)xi~TKHt8nj^t??d$(-sh3h-g z*whE(S}R7Su^KhLw@;I%F|JMjwjGP7F^efDBtw#3FOP1KHLAMz`FImL>TQcvOFIgjr{ms1(Ua*yQR(XUj zdBGw^Rf}HG;{_X@nq=|4$O~3tl1H(AMt zFYC9LAOD=q`*w5R=0?w13C{-?Ufq1g-aUF>d;jQX>|U*;F)wO9W2<*rPxp#{%BHui z;e3DaQ?@g0w|$4tDJ*_T;wZ<3DeO|WE^YSKPhlq;lr5qPe!}+do!GF#v}6|aF?MC- z(#Pzx$-~;hVP%!(SsR;NWXsDb z>fD)ehWYo~KjV)Thwyo4g%dmKf>K1(3uRa{~@KDghSoQ1mv#gG#EoDMEyD*|U{?{@=p7l&W+avw# z0w%~ai%@)fvSk`uv7FLuMs*`;>qEubTC7tTx*6{9dzI^Pr$gR!76sO%61Si>-8&>Pe~Gpktg?Ba3~JS1>BNbCLR&Sh?+y z>;&S+R|)dV;rFkzdeNI-V%0_0-nJ^b_y+M~=G;)_@UJZyK6TyL{c8WMyJDY>yT{wl zXfia1A6f2mSYZ2;>JA@^wjIJN`RH(=<(bLxb^UF|wtc*^r1*PE5Y z|F(X+$6uwcsPEJ$Uhln2D$gHQEHH;}qxrf#a^fX+rNj6kYhqsV{FaYr3H7J2zN0J_ zC$>1n>?>6q9u>y7L^HYs2Sf@b+K!3D41Qn!RIW^O%k7LDTbI z_G>eF`+I$+3H&5>duYGXwQB58?-}^#wPk)9UcZu`Du?gZtX~<~x|Qns^{#K2gX=of zFa0=fx==se|0_M#+ z>rXALUzX4MRp*ZMkB+kR^+}%Azc9bD^y?=+t^XXpUi*np>pzFD*MHtV)_)FP&ws?H z^&ba{l%?-~o{#mP!`B->o{#mP!`B;so{#k})Sse1e|SFDe-2-7{t=(nzhFN_fBq7m z)_;z^-u&n7WBupo>#ZN&KGwg$Ptsq1ygt@{4qtEm5}($;P=7q-MM-yGPHvIj{-Lk0 zzyIjh&-C^$;-`q(&-C^`USHII{r!{pV*fF{{g<~d^1uH6&D$4^AJg0adA?};ncn$> z=ZoeK(>wq0e9`=4dgm{mFPgth@BByn6w&-=dgo8#i`S3-`Iq?O^{0RS=Ix8tukN~o z%8^pkW%)EgDBr}Y#u(whk-C!N)US$DUh0+?yf!_raiOEO{By@i2^WK`y)C4?I!E^z z_*C^hFdv`4=%^I;a~)-2N)xM@Rs898cO)O-euOBB;e^DWmxvKXFLd9%K-D~3cfF%6 zEa0{9dZqAsg}>e@yk7b7^{)Q;lGd3-biG`7y`p`;qPyOreNnvM>R+!BU%X%I`;YjA z*DHnBE5h|wO5ycN-p>nYef+PwUO|753h%cpyx+3$e#^r9Eer3rEWF>c@P5m}`z;Ia zw=BHhvhaS(!uu@?@3$K*GD&!#OyVff)vu8Ih5Cj@ zO5})95*jM=4_8E5m2gwY5DJE(m4^HJLlYVz>kYyrVJf9EBorK(Z;%9ma3nz?p)%Ou zW8zR$6f3?1=mWK{MX3@^CHA?^P{FpVhqDVRKyaNQp&>!2LLMgZ4GWV6`6(hL0V+P2 zOE6-pj-+NlN*;{(Er{qcnvb(u!jt6X!2#4^88i_iXDITL$PiVixUE(a=Wq!`gF+A@ zRUscPgLUc-VvDF0h|D^K5A#EjW8f)jQ&aztASFVz21qQM`71&jN`|O{{i#RVcKRZ! zs?exlgqBhHhokfO=R4t~P`LWawSA|4+fctL0IV!HL^U)}5~lR^M}Hws@nR7UR^%|T zznbg$E2r-=?clk4YW*D^h(?DX1d-Lx`-AGCwpmjhj<7`S%dH?l;M=q%zAD()56#5P z$(4`<%6ygD*20cWn*#bcN-k35$1PW{b-sFG;QCBNuHWg}FG z28_ngEO!?+84Mr-<^;(xcQNT`ylJ|tf>mMUz)`;cjY}SVw&s2K!+9?Y#;An^2O+Kx z`arV04}U1@8#+`)f?>KbwdU6o0`*`jVZkaXo>I-ACqyXIxv&#OW3FAI1U7aO zYcC;XB!rTT|3!O9abM$2h2y27<2g8{_(zoHijL=rj^~Sx7l@7*ijEhFj*W~>Op6pP zW>&n!FC|NrE@NJ{T=@zWf2~xxO4VxBYt*bIsa>b8MZNkBEE_gz+@z^hGwbFyEn2o} z-KK53_8n~PIx?xfgQHWY&Rx1XckAxr+M}miFLw{m-d=tB_Uk`j;Gn_YKE8hb0kR=O z1LebpD}sVUlp{jJ!c`+jMMRDsGj`l>A1I^5eMJSb{l*&Bu zq9l&kixo1=*`9vGu*4)T6lOalv;i4#RN!2iC zWFH#p8wn+GS*|!vkP=Hy;u)!w=^63iw`qhB!-Vt4g5nqLP?c|JKm*PPvELAsJ3ulL z4a1J^AEJz;6K2jyL5>wCG}cFu8A$=w3Y3IDe#TxvBxWg^By3?6|64c}(aD9}!};iB za(8Z=rLw+6*yVa`p33Qb6~(AiN7Kw z3_HKJfBJk8*C!+>SgwuVCm%}VuCqY%CRjFVz#z0kJGLW-@cVzBk;|zjuMEcA-P6;V zeA}rj=c5V;$5jLZl?7un0`G6$$uYx;e5mvH4?8WA`=R?p{Cs8_+NL`#2FSy5U4(ey z@Plq{71Riw%nutteb1SnKkNeM6Nb~UZ>ZMgv`yz466U3Bh%a4wiF=UisvP_Lko`zs z+xR?IeY8RTwD$9?Sz)nKyTh@*LxyN&M$)AM#%!b?Kl)VYBg_Ok9*oUxEI?0{+uGW3 z9XsN2eH=FfngWf1M!?vykf{$!I>2v$CF1Bc0fh>O(+3B2j&2642T&~arX3q`P~l^O zH>EsY8aIYLo`?9^h%8Cl2C^K@)7sFt18O603qu`YRG82FTqZehZ(Oh_+*lwG=n6CeT)=Yz62O;&+5&BXmVhJSoP&-M1` zGUQ4heux5^}mm5;Q#atFq)9_XY`XvH-bbb8s+{O8~xm$PXF({|F4!9S^-p3 z1^nr1q+IT?Iero2zmoLjf3CN=Qs!LlvG&Nwh-O06go%?TPnkMx`iz;gX3v>BZ~lUX zixw|gx-5G6ij}KYuUQ+jZvBRhn_@R_*}84}j-9)9@7cR=|AB*t4j(ys?0DRXlj`_W zr_Y={cm6`c#Y>kHuUx&Bbp6K7Tet7ry?6h?!$*&kpQJo}_B{2)%U5Zy-@HxF$kb%L z`~CfgKR*7M{ps_Uuix+^S^w@E&HUd;{?r@I|8)QV)Aj$`{x|eSKYu>|M*lzE|E^uz z2L-hcHJhp30_bFfP` zIoKjQKrrX(8%Z`mLrItGhLF)76xTWc46+w0=Z`!CRiR-*Ssz(IuuRB!;$u82b`1&U zxgIKk`i7G(ey>f%L7syg$#CFv&Fl8+Vc!FnrFETqbVeOS=}NJAT@Sw8v1gB-y*({R z7Anw$0oZ{#vjx`E!HQ|KGIh@Mi1h16Ad@Gnq{k+{Z1ymShh?e5{^ z!EN|>Z{d^>rz2l_3=25A!jU#U|MmmJMg|YWrv*b1nSQ7|d?4O1;(d+ZK>G13Z{e!~ zS?EA_d^&)4CVItIO1;SXrb=9MGu?Hw_P5;TBfknbB9xO1zv-fW`re1SCIv`O0-i33 zdA9^z;*oBu$evD~s1xbqH^X#^WX+MUER^wlfho2x)*-eMcDm}>>5IINP)2-R65A2$ z5Z`(Pes4|BP7Lx}gfimmlGu(|hxlobyQgO-4f!mgjQF}FwjkwZ8xj;QT5y(dgWyIGdu^q7v@w-B9kDi@)hxnDl@xD{gp*;D=4f(!88S!;VY)7m^{K_i4{}kE5&sK5K z$ZrI6>wsj)J|(d&u^#b0pw3$&TP7$=MgD`HJ(8n(D2eTfb%`fMy%zY*1zjSYmdHy1 zUE4_JM{N`9k-iV)lp)9i@AGJ-aOZK857q4e83HcN~dnETGdtzO(=Y&1b z9DATHQJ*BpTMA{w*Cnyf#5%;MeM!6rQP~mbDnz!aJ!6rd4(R+yGC%U8SdVPA8Enki zk6CzG64INCR`v84O|8O0<6>~oB}umqyhEgO}GKTT;L>- z2~<91!npwvz#*X6X%o%`SPonUik>myIs(DKcHkvY^Q;Ny1xyD{0maTi1{ewK0+N9S z=S{c~z#8BwQ1*fe*8>;@YzOWEe*qQ==m!u1oCMN<$`?&IDG&@S01g1x0R2RBC~BW0 zzy79!*1_+b(7cG~oIB6NIy5&(XFFsm9TMs6C_sno;;SFdv`fKuUki3WfKpwh_G{Zl zd1}2b?}l=+Nit0euqg#!m-^P0a#CFebUgCZ7b?@`@X>a` zC)Adr%-BzGfza1#m-$|fupd=Rq zN;XL*(SXe)$WpooO7ba!F7+qdfUfzW+W@OCW8J-AAIukY)`)Zh4Ctf?I+-G!XahRd zM{>s{(SWQEWGMv-Iy5fX26X0%>^E^KxX*_L`)ZN>z6Nw&i0sccAZvD1I}X1J)B=>o zkmm0Z1G@bMS(^7B49G@_WF@Wz_j!Xz*2RGAd68^{0a=YmcB28=a>sJ#K#~DjsYv## z0a+zvDUA_yXueqT@96pBJTK%|S|fV|o#UWXc3#k>F&bz*rOC7 z&?r#y&n!^t%Tj@E6zFbH(t81_>x*@-g8d~qsjZ_iDD|Z^DCv^@fd+Ja1XjzPkysWZ%hvY?Me=X+U<5NOqM0*%Xm%f&p3cQ@LaH z!GNq3vXr_CI^++DXTknZitKwDkd1*Xjq7%i{U`%EDS}R>Nauh79qZG%eNHnVtAs4I zX^cQ;fKtB~2sUWWRp?!?58?$`niG8u$Yu%kd=Yf0uE_>;tk2~3=ZFDWACYXT0onPG zr4$WHZI2OjY0onED!9){g6=~>hx*}SK*#)SZa<<7$Vwqgsk@*<_IDW2i4xgQF(A7~ zBwMmi!F^4EEX|QjQCr#?(6K(3+gF7FSs%z!8ZPKiU!x7^#E9%C8jwvA$z~gn<<4vS zS{hWhCtCC^*gt(COUX^7)7OB`d_k7x-E0H034;B2k^LhEbc$Zc^?$knS*b|2a=(K6 zDi_H*8IX+;$tn%VCW&NM8IXN1l1(rmTO}da4<8K3N=34g{`vbsN`oyV)n|Kt@1Sv{ zc}vs(&8-Bl;Qnp|#2DZrN7J=>;+G+xsI6WJ@B3{TA z@y!O{^L;?~IT(E}K#A-TrJD<5g!Yv>)PNWYD1QujMy&KHA5s@ePI55BfTs5 z9c)UIAxFA9M7n(o(510h4E`QKHx~3g2qm&Zl*S?(zpYJ4`UBocfmdCik6?@Jrt8_I z??Whw?N%J*!2KoEb4#GQd@nz3ow|I29{-qsUcSEm_<(}>U1SCGN6sji|Lg36`3`gP z@{{!1zg&->DB|A&@0%W9zkmJb=C!ZScbQ)>-*REWd~Q|2{D!OZ^2P0sU*o{t0x0Rm zPrv_m_^otG-(wuO;yBjH-4prYCCW8`l$X@Lq^vi*CYyNYu1Q-Q)B1A(6(=gAq^tLU zs9q|syiwb}=^Grl1%OUY?C0;B95|EMy!{lnKN`GM0)GR36Q0snw8I$G%qMrv(RXl^ z&;)+X(f0s7w&%4gu9sw|?aFP_Qqi%vev)(ElPlL-bS#!Dz0ZLw2T;=WQ_LR>o}V6H ze?09E=G7O^2eRAju$E89Uk>HAX|~Ak2TwV0M*&K@cIel0>RevFzF*vL=g;r=)PYk0 zV*C2~e$Vpq_3MB7xnO>bkz*eF`ue+z=jDt2e5ITt_ZlduefJyX-W#4 zQ^EXSyXNKVk7H{0ynKE8mwV;q|E+xxFGsE? zAoinJ|F^!5+!8>{*YBswCof;DPkIA}=H=__Cn)ps<3;nF^mj()c8UZZ<7hoU|3d{tefo;GsAOUy)WCC2EDfcT-2e1O108d~D5DrWR76LKA zF5oPX415I4<){yE0z83Xz+_-PumXq$jsOY3BfxZ+DOV1t30MJ6fF}?Dj0C0wD}Zgl zG2jwF=|0yf7*FdthT;)(Joe&&C;I5o22Nw_BJ&+7`&;<|V`tsd=zn8&@8sU2lM9|= z2%yJpYMXi}WVkc%B<@M1huHK@Ei`ctSM&}Zg-0s5rly{{XLNI-2W&OM^Ae6KJeVJ> zd;EgyXxcj%4}J&W8TC#P{qpaUFN(bNOaW8}xaZtNW9B*T;PLuH|EcuWXJ zx&9{ZzVa|xjwOy;ZQK>lG21KfAQktL>ZfNo_{U#4ZXM6-94f;-k|BKCLV|FMUVw`{ zSZ2?Cq7v7T0F^@4m2Y4lj*}RpjQV3A5P&LiA7@KbPem9Cy?hn8chQD&+RC_Abc_yY zIV~v1R}~L`qkCx3a9MzJuzx83Tp+GBO&~04-A<9WJo%?JodfW$M68WF79H4k?xTM1?K$oV zStT7edRUo8sH%x8Jpt|z87}h-=_3!2IR@em(LfV-JP=NT95=_b4<@3F&x|(JiFk(O z=y8+yerg{|cXY#d1EM_K4;y_P9bB=hpH5{6zM&j@l zA9DLd?dgGMqtUBwMr5{A?z7w;xG^($XqY{xCi%ZJxbFFA^x;nZSOYW1)1;S578>a$ z3+1CqAj|dvU)pP>c>Yo<&BK%F zws(OSeZ!H92gLf0At9jwwCE9fM2Q(TRO;nw?*>Cc63a3RPYQM+^eQQA_+uOL4iEK}hlfd>wDm!ZZy7y~iZUCiw%Eg9@m3C?2r0v6hfBU_f+erVJ##-KV- z^dDQN&i}|Hcf0M#1p-mP7NW_HTr^<)1oIwnOVNIZWi0ediM)6$hxp1Bh~XfWF2Y@>o{6_`g|#c2oNP3Db?TOrS$mTDrzS>Rz-7M z7@$k~KA^A$-f~>YV7nw<*oaVilqVpA1lY5Zi}ChzM?tkY5K%?b!%WeVYN2I}A{t zt^&lr3lP6DoI?K5`Ao9L2|2V4RQtpzpVc}>IMflcW2DRcfD)fjmz=3J1BgG!WjaH6aRgkaG9l2_tA3$q? zrh}FzHfU|oN1&xaZ-LTYlL$)t=~+CT_oH0_Y|<8pFQf?$+6wnbsDi{h+vjs-UTgnO&gfwk8^D0A^U6KpdxQ!_IHXIfGV zFp41DUa*azW^B$W>N#?0fOiE)?i{ENy8IxN6Q&82WOefAQASC(2kWR{{inBw@FJUtWBY< zmXrP##nUa2Kege(28ovax7P`OX^W%+J@}LI_JaH&$X{EZy1pv+Vtv~B0r}hiZ5^-C z3l~hi9t?gU;k+LVd!V~u$W@zg^ImewC&c3TP1`b<=Onn-Jy$||?*pCp#Az`ufM~C6 zB%DY3c68!A0XM(}=n6OiQlKqh4Ojxz0dv3%_-cn31i%L%3rGjjfK(s_cm&)7ZUIR^ zB5)Qs0_*{{03;s+L<94I$-r1Z2?PK>z(Bwaum!Av;-`*P2bGPt>^!$xE=?Nrt=@~Ob9+{K zJ4rfX>D?ucrHjmIxOw_Ui+qPbg>t2q0p7?viW|Jq>cd|6Ev@Ls=`SWvU zKRdnMeCz$6Z=ZG>z2sUaS>lBSrDJ!+RC&Ikb17M+lBx+)RU{NaOk!r+3y>u*Cz~m z92M+xapf|}Ok;PSv-MQyFLx#JN}@J>VI%BH+})t0mu%KQpu>}%bCv~{oAd`ebF+!8 z%Co+e4qt!AlFHPb+@)HV9p^S@GHL7~xng&b6K$rxWi9OD97eymy;yzc6+8Xy+g0Dm zWk)4$Pi4(q20V2=dvfuTmlxT>vmPB(PFE_NT(O%a4?VWHU8kKj_g-7fEb5+r7I&;e zbKhB`nQ!lYr+(Y(F}B=sZ+17c*_@&$7fz}8#fe$4O|RQ+YVcQb8H^J!?yN}>uo1?S$2f`cDKW$>3z+r?M-_= zHP)oV`N^FeiXB?6YV**leTxy*Z`6Hglj%Iaf4kUeC*%7(*fcSA{Xv^&f&0pCc389P4C}lfvwtYQk}{@y372&O`5m6 z=;Co@Q=2BQy?P_T^l|LH5;UJ{!p9we{s3JQF9Qw&w}AIRSuAR6pa&2H=yckH*AEy4 zECmh#H-X;)bI3IVTmc2}|6{^7hGfLQPr;rQ#b@!NE2nN*|Dc@q)UM$5-DAr2hfu0k zfwL7NB1K9ff)v4Fc6AV#xP6#^pe)EYtSMqeYlETFuN$=Y4GXdw*}RSfH*Uy>AXuyy zzP!dgBzAS0TUpoXSgM3XVvBInVd3=M@lRT7q1A(Cn9LtP-Vh$i+o4M^+nkW}ZlUs# z_(p4}EG&m9W_OB!D&5TDA{!}FNEGyHSI0NZIe28qa9L;_iArwo?~hwZ?CK2hRfNgv zbhK@jV>_>Mj(w5D-)gsQmZz<@&2l;ob=zh-e|B`Uce8hL!cTGZ?JFGoJNf?ymwf}F literal 184320 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⁡Z2k6h~M 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 diff --git a/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe b/contrib/vmap_extract_assembler_bin/vmapextract_v2.exe index c38b6e64f64b69a6e093c8e7d9b71f7d0b5ad15e..03c76907658990e6657f372ace9b168868599de1 100644 GIT binary patch delta 115477 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

FcbfD!>T|*<3xE%nn5in`+&P+QFm*kPV#7F$ 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�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 diff --git a/src/game/Map.cpp b/src/game/Map.cpp index f60395953..e0f37dad2 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -613,7 +613,6 @@ void Map::Update(const uint32 &t_diff) } } - // Don't unload grids if it's battleground, since we may have manually added GOs,creatures, those doesn't load from DB at grid re-load ! // This isn't really bother us, since as soon as we have instanced BG-s, the whole map unloads as the BG gets ended if (IsBattleGroundOrArena()) @@ -1112,7 +1111,6 @@ uint8 Map::GetTerrainType(float x, float y ) const return GridMaps[gx][gy]->terrain_type[(int)(lx)][(int)(ly)]; else return 0; - } float Map::GetWaterLevel(float x, float y ) const From 5fae2418ab6a45227a0766767dce27c14f1aa579 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 23 Nov 2008 16:18:14 +0300 Subject: [PATCH 113/256] Misc fixes --- .../vmap_extractor_v2/vmapextract/model.cpp | 2 +- src/game/CalendarHandler.cpp | 10 ++ src/game/Level1.cpp | 6 +- src/game/MiscHandler.cpp | 4 +- src/game/MovementHandler.cpp | 103 ++++++++++++------ src/game/Object.cpp | 12 +- src/game/Opcodes.cpp | 18 +-- src/game/Opcodes.h | 8 +- src/game/Player.cpp | 16 +-- src/game/SpellAuras.cpp | 8 +- src/game/SpellEffects.cpp | 2 +- src/game/Unit.cpp | 72 ++++++------ src/game/Unit.h | 20 ++-- src/game/Vehicle.cpp | 8 ++ src/game/Vehicle.h | 2 + src/game/WorldSession.h | 5 +- 16 files changed, 176 insertions(+), 120 deletions(-) diff --git a/contrib/vmap_extractor_v2/vmapextract/model.cpp b/contrib/vmap_extractor_v2/vmapextract/model.cpp index 31962a001..1d0c17d52 100644 --- a/contrib/vmap_extractor_v2/vmapextract/model.cpp +++ b/contrib/vmap_extractor_v2/vmapextract/model.cpp @@ -39,10 +39,10 @@ bool Model::open() else { //printf("not included %s\n", filename.c_str()); + f.close(); return false; } return true; - } diff --git a/src/game/CalendarHandler.cpp b/src/game/CalendarHandler.cpp index e548a6696..a2a30b72a 100644 --- a/src/game/CalendarHandler.cpp +++ b/src/game/CalendarHandler.cpp @@ -106,3 +106,13 @@ void WorldSession::HandleCalendarComplain(WorldPacket &recv_data) sLog.outDebug("WORLD: CMSG_CALENDAR_COMPLAIN"); recv_data.hexlike(); } + +void WorldSession::HandleCalendarPendingInvites(WorldPacket &recv_data) +{ + sLog.outDebug("WORLD: CMSG_CALENDAR_PENDING_INVITES"); + recv_data.hexlike(); + + WorldPacket data(SMSG_CALENDAR_PENDING_INVITES, 4); + data << uint32(0); // 0 - no pending invites, 1 - some pending invites + SendPacket(&data); +} diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 5730ad1d6..c73231635 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -1028,7 +1028,7 @@ bool ChatHandler::HandleModifyASpeedCommand(const char* args) chr->SetSpeed(MOVE_RUN, ASpeed,true); chr->SetSpeed(MOVE_SWIM, ASpeed,true); //chr->SetSpeed(MOVE_TURN, ASpeed,true); - chr->SetSpeed(MOVE_FLY, ASpeed,true); + chr->SetSpeed(MOVE_FLIGHT, ASpeed,true); return true; } @@ -1144,7 +1144,7 @@ bool ChatHandler::HandleModifyBWalkCommand(const char* args) if (needReportToTarget(chr)) ChatHandler(chr).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, GetName(), BSpeed); - chr->SetSpeed(MOVE_WALKBACK,BSpeed,true); + chr->SetSpeed(MOVE_RUN_BACK,BSpeed,true); return true; } @@ -1176,7 +1176,7 @@ bool ChatHandler::HandleModifyFlyCommand(const char* args) if (needReportToTarget(chr)) ChatHandler(chr).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, GetName(), FSpeed); - chr->SetSpeed(MOVE_FLY,FSpeed,true); + chr->SetSpeed(MOVE_FLIGHT,FSpeed,true); return true; } diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index 917867993..4dd956a55 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -1493,11 +1493,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_; diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 9ef0b6649..9c5570563 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -171,19 +171,12 @@ void WorldSession::HandleMoveWorldportAckOpcode() void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { uint32 opcode = recv_data.GetOpcode(); - sLog.outDebug("WORLD: Recvd %s (%u,0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); + sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode); if(GetPlayer()->GetDontMove()) return; /* extract packet */ - if(opcode == CMSG_MOVE_NOT_ACTIVE_MOVER) - { - CHECK_PACKET_SIZE(recv_data, recv_data.rpos()+8); - uint64 old_mover_guid; - recv_data >> old_mover_guid; - } - MovementInfo movementInfo; ReadMovementInfo(recv_data, &movementInfo); /*----------------*/ @@ -218,9 +211,6 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) { if ((*iter)->GetGUID() == movementInfo.t_guid) { - // unmount before boarding - _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); - GetPlayer()->m_transport = (*iter); (*iter)->AddPassenger(GetPlayer()); break; @@ -237,6 +227,7 @@ 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). @@ -245,11 +236,11 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) // calculate total z distance of the fall // it is currently only used for the achievement system. It might be used in a more correct falldamage formula later float z_diff = GetPlayer()->m_fallMovementInfo.z - movementInfo.z; - sLog.outDebug("zDiff = %f", z_diff); + sLog.outDebug("zDiff = %f, falltime = %u", z_diff, movementInfo.fallTime); Player *target = GetPlayer(); //Players with Feather Fall or low fall time, or physical immunity (charges used) are ignored - if (movementInfo.fallTime > 1500 && !target->isDead() && !target->isGameMaster() && + if (movementInfo.fallTime > 1300 && !target->isDead() && !target->isGameMaster() && !target->HasAuraType(SPELL_AURA_HOVER) && !target->HasAuraType(SPELL_AURA_FEATHER_FALL) && !target->HasAuraType(SPELL_AURA_FLY) && !target->IsImmunedToDamage(SPELL_SCHOOL_MASK_NORMAL,true) ) { @@ -257,10 +248,10 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) int32 safe_fall = target->GetTotalAuraModifier(SPELL_AURA_SAFE_FALL); uint32 fall_time = (movementInfo.fallTime > (safe_fall*10)) ? movementInfo.fallTime - (safe_fall*10) : 0; - if(fall_time > 1500) //Prevent damage if fall time < 1500 + if(fall_time > 1300) //Prevent damage if fall time < 1300 { //Fall Damage calculation - float fallperc = float(fall_time)/1500; + float fallperc = float(fall_time)/1300; uint32 damage = (uint32)(((fallperc*fallperc -1) / 9 * target->GetMaxHealth())*sWorld.getRate(RATE_DAMAGE_FALL)); float height = movementInfo.z; @@ -289,24 +280,19 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) } } - if(opcode == CMSG_DISMISS_CONTROLLED_VEHICLE) - { - // using charm guid, because we don't have vehicle guid... - if(Vehicle *vehicle = ObjectAccessor::GetVehicle(_player->GetCharmGUID())) - _player->ExitVehicle(vehicle); - } - 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) ); } + if(opcode != MSG_MOVE_FALL_LAND && !(movementInfo.flags & MOVEMENTFLAG_FALLING)) + _player->m_fallMovementInfo = movementInfo; // save data before any fall /*----------------------*/ /* process position-change */ Unit *mover = _player->m_mover; - recv_data.put(6, getMSTime()); // offset flags(4) + unk(2) + recv_data.put(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()); @@ -334,8 +320,8 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) } } - if (GetPlayer()->m_fallMovementInfo.fallTime >= movementInfo.fallTime || GetPlayer()->m_fallMovementInfo.z <=movementInfo.z) - GetPlayer()->m_fallMovementInfo = movementInfo; + //if (GetPlayer()->m_fallMovementInfo.fallTime >= movementInfo.fallTime || GetPlayer()->m_fallMovementInfo.z <=movementInfo.z) + // GetPlayer()->m_fallMovementInfo = movementInfo; if(GetPlayer()->isMovingOrTurning()) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); @@ -361,7 +347,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) { - sLog.outDebug("WORLD: Recvd %s (%u,0x%X) opcode", LookupOpcodeName(recv_data.GetOpcode()), recv_data.GetOpcode(), recv_data.GetOpcode()); + 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); @@ -378,7 +364,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) // continue parse packet - recv_data >> unk1; // counter + recv_data >> unk1; // counter or moveEvent MovementInfo movementInfo; ReadMovementInfo(recv_data, &movementInfo); @@ -394,19 +380,20 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data) UnitMoveType move_type; UnitMoveType force_move_type; - static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "Walkback", "Swim", "Swimback", "Turn", "Fly", "Flyback", "Pitch" }; + 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) { - case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break; - case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break; - case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_WALKBACK; force_move_type = MOVE_WALKBACK; break; - case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break; - case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIMBACK; force_move_type = MOVE_SWIMBACK; break; - case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN; force_move_type = MOVE_TURN; break; - case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLY; force_move_type = MOVE_FLY; break; - case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLYBACK; force_move_type = MOVE_FLYBACK; break; + case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break; + case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break; + case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break; + case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break; + case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break; + 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; @@ -451,6 +438,50 @@ void WorldSession::HandleSetActiveMoverOpcode(WorldPacket &recv_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::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(); } } diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 8af7dbe5c..1c8ad7bed 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -384,13 +384,13 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint8 flags, uint32 flags2) *data << ((Unit*)this)->GetSpeed( MOVE_WALK ); *data << ((Unit*)this)->GetSpeed( MOVE_RUN ); - *data << ((Unit*)this)->GetSpeed( MOVE_SWIMBACK ); + *data << ((Unit*)this)->GetSpeed( MOVE_SWIM_BACK ); *data << ((Unit*)this)->GetSpeed( MOVE_SWIM ); - *data << ((Unit*)this)->GetSpeed( MOVE_WALKBACK ); - *data << ((Unit*)this)->GetSpeed( MOVE_FLY ); - *data << ((Unit*)this)->GetSpeed( MOVE_FLYBACK ); - *data << ((Unit*)this)->GetSpeed( MOVE_TURN ); - *data << ((Unit*)this)->GetSpeed( MOVE_PITCH ); + *data << ((Unit*)this)->GetSpeed( MOVE_RUN_BACK ); + *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) diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index 91ae5a39c..cde8c4df8 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -747,7 +747,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*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::HandleMovementOpcodes }, + /*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 }, @@ -939,7 +939,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*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 }, + /*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 }, @@ -1121,8 +1121,8 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*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_CALENDAR_ON_LOGIN",STATUS_LOGGEDIN,&WorldSession::HandleCalendarGetCalendar }, - /*0x448*/ { "SMSG_CALENDAR_EVENT_RESERVED_3", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x447*/ { "CMSG_CALENDAR_PENDING_INVITES", STATUS_LOGGEDIN, &WorldSession::HandleCalendarPendingInvites }, + /*0x448*/ { "SMSG_CALENDAR_PENDING_INVITES", 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 }, @@ -1159,7 +1159,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*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::HandleMovementOpcodes }, + /*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 }, @@ -1205,11 +1205,11 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*0x498*/ { "SMSG_SERVER_FIRST_ACHIEVEMENT", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x499*/ { "SMSG_PET_LEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x49A*/ { "SMSG_PET_UNLEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x49B*/ { "UMSG_UNKNOWN_1179", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*0x49B*/ { "CMSG_MOVE_UNKNOWN_1179", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x49C*/ { "CMSG_UNKNOWN_1180", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x49D*/ { "SMSG_UNKNOWN_1181", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x49E*/ { "SMSG_UNKNOWN_1182", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x49F*/ { "SMSG_UNKNOWN_1183", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49D*/ { "SMSG_SHOW_VEHICLE_UI", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49E*/ { "SMSG_CRITERIA_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, + /*0x49F*/ { "SMSG_ACHIEVEMENT_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, /*0x4A0*/ { "UMSG_UNKNOWN_1184", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4A1*/ { "UMSG_UNKNOWN_1185", STATUS_NEVER, &WorldSession::Handle_NULL }, /*0x4A2*/ { "UMSG_UNKNOWN_1186", STATUS_NEVER, &WorldSession::Handle_NULL }, diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 078ef60d1..83f33d0f2 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -1123,8 +1123,8 @@ enum Opcodes SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x444, SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x445, CMSG_CALENDAR_COMPLAIN = 0x446, - CMSG_CALENDAR_GET_CALENDAR_ON_LOGIN = 0x447, - SMSG_CALENDAR_EVENT_RESERVED_3 = 0x448, + CMSG_CALENDAR_PENDING_INVITES = 0x447, + SMSG_CALENDAR_PENDING_INVITES = 0x448, CMSG_SAVE_DANCE = 0x449, SMSG_NOTIFY_DANCE = 0x44A, CMSG_PLAY_DANCE = 0x44B, @@ -1207,9 +1207,9 @@ enum Opcodes SMSG_SERVER_FIRST_ACHIEVEMENT = 0x498, SMSG_PET_LEARNED_SPELL = 0x499, // uint16 spellid, Your pet learned spell: %s SMSG_PET_UNLEARNED_SPELL = 0x49A, // uint16 spellid, Your pet unlearned %s - CMSG_UNKNOWN_1179 = 0x49B, // movement opcode + CMSG_MOVE_UNKNOWN_1179 = 0x49B, // movement opcode CMSG_UNKNOWN_1180 = 0x49C, // LUA: HearthAndResurrectFromArea - SMSG_UNKNOWN_1181 = 0x49D, // empty + SMSG_SHOW_VEHICLE_UI = 0x49D, // empty SMSG_CRITERIA_REMOVE = 0x49E, // uint32, broadcasts EVENT_CRITERIA_UPDATE SMSG_ACHIEVEMENT_REMOVE = 0x49F, // uint32, broadcasts EVENT_ACHIEVEMENT_EARNED UMSG_UNKNOWN_1184 = 0x4A0, // not found in client diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 65219c89b..0e26a8414 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18651,20 +18651,15 @@ void Player::EnterVehicle(Vehicle *vehicle) { vehicle->SetCharmerGUID(GetGUID()); vehicle->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - //vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); vehicle->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); vehicle->setFaction(getFaction()); - //vehicle->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); - //vehicle->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 2147483647); - //vehicle->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); - //vehicle->SetUInt32Value(UNIT_FIELD_BYTES_1, 0x02000000); SetCharm(vehicle); // charm SetFarSight(vehicle->GetGUID()); // set view SetClientControl(vehicle, 1); // redirect controls to vehicle - WorldPacket data(SMSG_UNKNOWN_1181, 0); // shows vehicle UI? + WorldPacket data(SMSG_SHOW_VEHICLE_UI, 0); // shows vehicle UI? GetSession()->SendPacket(&data); data.Initialize(MSG_MOVE_TELEPORT_ACK, 30); @@ -18677,11 +18672,11 @@ void Player::EnterVehicle(Vehicle *vehicle) data << vehicle->GetPositionY(); // y data << vehicle->GetPositionZ(); // z data << vehicle->GetOrientation(); // o - // transport part + // transport part, TODO: load/calculate seat offsets data << uint64(vehicle->GetGUID()); // transport guid data << float(0); // transport offsetX data << float(0); // transport offsetY - data << float(2); // transport offsetZ + data << float(3); // transport offsetZ data << float(0); // transport orientation data << uint32(getMSTime()); // transport time data << uint8(0); // seat @@ -18689,6 +18684,9 @@ void Player::EnterVehicle(Vehicle *vehicle) data << uint32(0); // fall time GetSession()->SendPacket(&data); + vehicle->SetSpeed(MOVE_RUN, vehicle->GetCreatureInfo()->speed, true); + vehicle->SetSpeed(MOVE_FLIGHT, vehicle->GetCreatureInfo()->speed, true); + data.Initialize(SMSG_PET_SPELLS, 8+4+4+4+4*10+1+1); data << uint64(vehicle->GetGUID()); data << uint32(0x00000000); @@ -18707,10 +18705,8 @@ void Player::ExitVehicle(Vehicle *vehicle) { vehicle->SetCharmerGUID(0); vehicle->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - //vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); vehicle->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNKNOWN5); vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H); - //vehicle->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0); SetCharm(NULL); SetFarSight(NULL); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 64c6afaf0..713e04801 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3698,7 +3698,7 @@ void Aura::HandleAuraModIncreaseFlightSpeed(bool apply, bool Real) m_target->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID,16314); } - m_target->UpdateSpeed(MOVE_FLY, true); + m_target->UpdateSpeed(MOVE_FLIGHT, true); } void Aura::HandleAuraModIncreaseSwimSpeed(bool /*apply*/, bool Real) @@ -3718,7 +3718,7 @@ void Aura::HandleAuraModDecreaseSpeed(bool /*apply*/, bool Real) m_target->UpdateSpeed(MOVE_RUN, true); m_target->UpdateSpeed(MOVE_SWIM, true); - m_target->UpdateSpeed(MOVE_FLY, true); + m_target->UpdateSpeed(MOVE_FLIGHT, true); } void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real) @@ -3729,7 +3729,7 @@ void Aura::HandleAuraModUseNormalSpeed(bool /*apply*/, bool Real) m_target->UpdateSpeed(MOVE_RUN, true); m_target->UpdateSpeed(MOVE_SWIM, true); - m_target->UpdateSpeed(MOVE_FLY, true); + m_target->UpdateSpeed(MOVE_FLIGHT, true); } /*********************************************************/ @@ -6362,6 +6362,6 @@ void Aura::HandleAuraControlVehicle(bool apply, bool Real) if(Pet *pet = m_target->GetPet()) pet->Remove(PET_SAVE_AS_CURRENT); - WorldPacket data(SMSG_UNKNOWN_1181, 0); + WorldPacket data(SMSG_SHOW_VEHICLE_UI, 0); ((Player*)m_target)->GetSession()->SendPacket(&data); } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index e39a16c4f..5aa29054a 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -892,7 +892,7 @@ void Spell::EffectDummy(uint32 i) if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED)) return; - float flyspeed = m_caster->GetSpeedRate(MOVE_FLY); + float flyspeed = m_caster->GetSpeedRate(MOVE_FLIGHT); float speed = m_caster->GetSpeedRate(MOVE_RUN); m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 98253c1a9..9c7137a99 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -50,13 +50,13 @@ float baseMoveSpeed[MAX_MOVE_TYPE] = { 2.5f, // MOVE_WALK 7.0f, // MOVE_RUN - 1.25f, // MOVE_WALKBACK + 1.25f, // MOVE_RUN_BACK 4.722222f, // MOVE_SWIM - 4.5f, // MOVE_SWIMBACK - 3.141594f, // MOVE_TURN - 7.0f, // MOVE_FLY - 4.5f, // MOVE_FLYBACK - 3.14f // MOVE_PITCH + 4.5f, // MOVE_SWIM_BACK + 3.141594f, // MOVE_TURN_RATE + 7.0f, // MOVE_FLIGHT + 4.5f, // MOVE_FLIGHT_BACK + 3.14f // MOVE_PITCH_RATE }; // auraTypes contains attacker auras capable of proc'ing cast auras @@ -8857,16 +8857,16 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) } break; } - case MOVE_WALKBACK: + case MOVE_RUN_BACK: return; case MOVE_SWIM: { main_speed_mod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_SWIM_SPEED); break; } - case MOVE_SWIMBACK: + case MOVE_SWIM_BACK: return; - case MOVE_FLY: + case MOVE_FLIGHT: { if (IsMounted()) // Use on mount auras main_speed_mod = GetMaxPositiveAuraModifier(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED); @@ -8876,7 +8876,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) non_stack_bonus = (100.0 + GetMaxPositiveAuraModifier(SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK))/100.0f; break; } - case MOVE_FLYBACK: + case MOVE_FLIGHT_BACK: return; default: sLog.outError("Unit::UpdateSpeed: Unsupported move type (%d)", mtype); @@ -8891,7 +8891,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) { case MOVE_RUN: case MOVE_SWIM: - case MOVE_FLY: + case MOVE_FLIGHT: { // Normalize speed by 191 aura SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED if need // TODO: possible affect only on MOVE_RUN @@ -8943,28 +8943,31 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool 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_WALKBACK: - data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + case MOVE_RUN_BACK: + 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_SWIMBACK: - data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + case MOVE_SWIM_BACK: + data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4); break; - case MOVE_TURN: - data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+1+4+4+4+4+4+4+4); + case MOVE_TURN_RATE: + data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+2+4+4+4+4+4+4+4); break; - case MOVE_FLY: - data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+1+4+4+4+4+4+4+4); + case MOVE_FLIGHT: + data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+2+4+4+4+4+4+4+4); break; - case MOVE_FLYBACK: - data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+1+4+4+4+4+4+4+4); + case MOVE_FLIGHT_BACK: + 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); @@ -8972,14 +8975,14 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) } data.append(GetPackGUID()); - data << uint32(0); //movement flags - data << uint16(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 ); } @@ -8996,30 +8999,33 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) case MOVE_RUN: data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17); break; - case MOVE_WALKBACK: + case MOVE_RUN_BACK: data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16); break; case MOVE_SWIM: data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16); break; - case MOVE_SWIMBACK: + case MOVE_SWIM_BACK: data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16); break; - case MOVE_TURN: + case MOVE_TURN_RATE: data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16); break; - case MOVE_FLY: + case MOVE_FLIGHT: data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16); break; - case MOVE_FLYBACK: + 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; } data.append(GetPackGUID()); - data << (uint32)0; + data << (uint32)0; // moveEvent, NUM_PMOVE_EVTS = 0x39 if (mtype == MOVE_RUN) data << uint8(0); // new 2.1.0 data << float(GetSpeed(mtype)); diff --git a/src/game/Unit.h b/src/game/Unit.h index 46cedc379..99bbf62ab 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -376,18 +376,18 @@ enum UnitState enum UnitMoveType { - MOVE_WALK = 0, - MOVE_RUN = 1, - MOVE_WALKBACK = 2, - MOVE_SWIM = 3, - MOVE_SWIMBACK = 4, - MOVE_TURN = 5, - MOVE_FLY = 6, - MOVE_FLYBACK = 7, - MOVE_PITCH = 8 + MOVE_WALK = 0, + MOVE_RUN = 1, + MOVE_RUN_BACK = 2, + MOVE_SWIM = 3, + MOVE_SWIM_BACK = 4, + MOVE_TURN_RATE = 5, + MOVE_FLIGHT = 6, + MOVE_FLIGHT_BACK = 7, + MOVE_PITCH_RATE = 8 }; -#define MAX_MOVE_TYPE 9 +#define MAX_MOVE_TYPE 9 extern float baseMoveSpeed[MAX_MOVE_TYPE]; diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp index 12acd640e..e70d7c75f 100644 --- a/src/game/Vehicle.cpp +++ b/src/game/Vehicle.cpp @@ -94,3 +94,11 @@ bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, u return true; } + +void Vehicle::Dismiss() +{ + SendObjectDeSpawnAnim(GetGUID()); + CombatStop(); + CleanupsBeforeDelete(); + AddObjectToRemoveList(); +} diff --git a/src/game/Vehicle.h b/src/game/Vehicle.h index 0479d96f8..7fd8b60c4 100644 --- a/src/game/Vehicle.h +++ b/src/game/Vehicle.h @@ -40,6 +40,8 @@ class Vehicle : public Creature uint32 GetVehicleId() { return m_vehicleId; } void SetVehicleId(uint32 vehicleid) { m_vehicleId = vehicleid; } + void Dismiss(); + protected: uint32 m_vehicleId; diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index f2071fcb5..f855f1597 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -334,6 +334,8 @@ class MANGOS_DLL_SPEC WorldSession void HandleMovementOpcodes(WorldPacket& recvPacket); void HandleSetActiveMoverOpcode(WorldPacket &recv_data); + void HandleMoveNotActiveMover(WorldPacket &recv_data); + void HandleDismissControlledVehicle(WorldPacket &recv_data); void HandleMoveTimeSkippedOpcode(WorldPacket &recv_data); void HandleRequestRaidInfoOpcode( WorldPacket & recv_data ); @@ -592,7 +594,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleLfgSetCommentOpcode(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); @@ -654,6 +656,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleCalendarEventStatus(WorldPacket& recv_data); void HandleCalendarEventModeratorStatus(WorldPacket& recv_data); void HandleCalendarComplain(WorldPacket& recv_data); + void HandleCalendarPendingInvites(WorldPacket& recv_data); void HandleSpellClick(WorldPacket& recv_data); void HandleAlterAppearance(WorldPacket& recv_data); From 6baaad4ed37a0fb1a4a01ee99ff54c0aaf640cb2 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 23 Nov 2008 17:18:54 +0300 Subject: [PATCH 114/256] Allow speed change for units --- src/game/Unit.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 9c7137a99..6b6830d25 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -8933,10 +8933,6 @@ 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) { @@ -8988,9 +8984,13 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) } 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: From 943963df7e6423aca4804d8e1df3e71992fb9e95 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 26 Nov 2008 19:47:07 +0300 Subject: [PATCH 115/256] Added vehicle*.dbc --- src/game/Player.cpp | 17 ++++++++++------ src/game/Unit.h | 4 ++-- src/game/Vehicle.cpp | 2 -- src/game/debugcmds.cpp | 10 +++++++++- src/shared/Database/DBCStores.cpp | 4 ++++ src/shared/Database/DBCStores.h | 2 ++ src/shared/Database/DBCfmt.cpp | 2 ++ src/shared/vmap/VMapManager.cpp | 33 ++++++++++++++++++++----------- 8 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 36cb3f2df..074963e7e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18659,6 +18659,14 @@ void Player::InitGlyphsForLevel() 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_UNKNOWN5); @@ -18684,9 +18692,9 @@ void Player::EnterVehicle(Vehicle *vehicle) data << vehicle->GetOrientation(); // o // transport part, TODO: load/calculate seat offsets data << uint64(vehicle->GetGUID()); // transport guid - data << float(0); // transport offsetX - data << float(0); // transport offsetY - data << float(3); // transport offsetZ + 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 @@ -18694,9 +18702,6 @@ void Player::EnterVehicle(Vehicle *vehicle) data << uint32(0); // fall time GetSession()->SendPacket(&data); - vehicle->SetSpeed(MOVE_RUN, vehicle->GetCreatureInfo()->speed, true); - vehicle->SetSpeed(MOVE_FLIGHT, vehicle->GetCreatureInfo()->speed, true); - data.Initialize(SMSG_PET_SPELLS, 8+4+4+4+4*10+1+1); data << uint64(vehicle->GetGUID()); data << uint32(0x00000000); diff --git a/src/game/Unit.h b/src/game/Unit.h index 99bbf62ab..289317472 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -167,7 +167,7 @@ enum UnitBytes2_Flags UNIT_BYTE2_FLAG_UNK1 = 0x02, UNIT_BYTE2_FLAG_FFA_PVP = 0x04, UNIT_BYTE2_FLAG_SANCTUARY = 0x08, - UNIT_BYTE2_FLAG_AURAS = 0x10, // show positive auras as positive, and allow its dispel + UNIT_BYTE2_FLAG_UNK4 = 0x10, UNIT_BYTE2_FLAG_UNK5 = 0x20, UNIT_BYTE2_FLAG_UNK6 = 0x40, UNIT_BYTE2_FLAG_UNK7 = 0x80 @@ -1149,7 +1149,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject AuraList const& GetSingleCastAuras() const { return m_scAuras; } SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY]; - // Threat related methodes + // Threat related methods bool CanHaveThreatList() const; void AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); float ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL); diff --git a/src/game/Vehicle.cpp b/src/game/Vehicle.cpp index e70d7c75f..4e1153a16 100644 --- a/src/game/Vehicle.cpp +++ b/src/game/Vehicle.cpp @@ -82,8 +82,6 @@ bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, u SetVehicleId(vehicleId); SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - //SetUInt32Value(UNIT_FIELD_BYTES_1, 0x02000001); - //SetUInt32Value(UNIT_FIELD_BYTES_2, 0x00000001); SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); CreatureInfo const *ci = GetCreatureInfo(); diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index fe6b88760..41d74b2d8 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -534,7 +534,15 @@ bool ChatHandler::HandleSpawnVehicle(const char* args) uint32 entry = (uint32)atoi(e); uint32 id = (uint32)atoi(i); - // TODO: check entry, id... + 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(); diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp index cc817014c..c8cce9da6 100644 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -132,6 +132,8 @@ TaxiPathNodesByPath sTaxiPathNodesByPath; static DBCStorage sTaxiPathNodeStore(TaxiPathNodeEntryfmt); DBCStorage sTotemCategoryStore(TotemCategoryEntryfmt); +DBCStorage sVehicleStore(VehicleEntryfmt); +DBCStorage sVehicleSeatStore(VehicleSeatEntryfmt); DBCStorage sWorldMapAreaStore(WorldMapAreaEntryfmt); DBCStorage sWorldSafeLocsStore(WorldSafeLocsEntryfmt); @@ -437,6 +439,8 @@ void LoadDBCStores(std::string dataPath) sTaxiPathNodeStore.Clear(); 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"); diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h index b5c268258..3478b3d14 100644 --- a/src/shared/Database/DBCStores.h +++ b/src/shared/Database/DBCStores.h @@ -200,6 +200,8 @@ extern TaxiMask sTaxiNodesMask; extern TaxiPathSetBySource sTaxiPathSetBySource; extern TaxiPathNodesByPath sTaxiPathNodesByPath; extern DBCStorage sTotemCategoryStore; +extern DBCStorage sVehicleStore; +extern DBCStorage sVehicleSeatStore; //extern DBCStorage sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates extern DBCStorage sWorldSafeLocsStore; diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 679e36d54..fd7e28b01 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -84,5 +84,7 @@ const char TaxiNodesEntryfmt[]="nifffxxxxxxxxxxxxxxxxxii"; const char TaxiPathEntryfmt[]="niii"; const char TaxiPathNodeEntryfmt[]="diiifffiixx"; const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii"; +const char VehicleEntryfmt[]="niffffiiiiiiiiffffiiiiiifffffffffffssssfifi"; +const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiii"; const char WorldMapAreaEntryfmt[]="xinxffffix"; const char WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx"; diff --git a/src/shared/vmap/VMapManager.cpp b/src/shared/vmap/VMapManager.cpp index 86e017c96..a93f2a827 100644 --- a/src/shared/vmap/VMapManager.cpp +++ b/src/shared/vmap/VMapManager.cpp @@ -275,10 +275,12 @@ namespace VMAP { dirFileName = getDirFileName(pMapId); } - size_t len = pBasePath.length() + dirFileName.length(); - char *filenameBuffer = new char[len+1]; - sprintf(filenameBuffer, "%s%s", pBasePath.c_str(), dirFileName.c_str()); - FILE* df = fopen(filenameBuffer, "rb"); + //size_t len = pBasePath.length() + dirFileName.length(); + //char *filenameBuffer = new char[len+1]; + //sprintf(filenameBuffer, "%s%s", pBasePath.c_str(), dirFileName.c_str()); + std::string fb = pBasePath + dirFileName; + //FILE* df = fopen(filenameBuffer, "rb"); + FILE* df = fopen(fb.c_str(), "rb"); if(df) { char lineBuffer[FILENAMEBUFFER_SIZE]; @@ -288,8 +290,12 @@ namespace VMAP chomp(name); if(name.length() >1) { - sprintf(filenameBuffer, "%s%s", pBasePath.c_str(), name.c_str()); - FILE* df2 = fopen(filenameBuffer, "rb"); + //size_t len2 = pBasePath.length() + name.length(); + //char *filenameBuffer2 = new char[len2+1]; + //sprintf(filenameBuffer2, "%s%s", pBasePath.c_str(), name.c_str()); + std::string fb2 = pBasePath + name; + //FILE* df2 = fopen(filenameBuffer2, "rb"); + FILE* df2 = fopen(fb2.c_str(), "rb"); if(df2) { char magic[8]; @@ -298,11 +304,12 @@ namespace VMAP result = true; fclose(df2); } + //delete[] filenameBuffer2; } } fclose(df); } - delete[] filenameBuffer; + //delete[] filenameBuffer; return result; } @@ -659,14 +666,16 @@ namespace VMAP bool MapTree::loadMap(const std::string& pDirFileName, unsigned int pMapTileIdent) { bool result = true; - size_t len = iBasePath.length() + pDirFileName.length(); - char *filenameBuffer = new char[len+1]; + //size_t len = iBasePath.length() + pDirFileName.length(); + //char *filenameBuffer = new char[len+1]; if(!hasDirFile(pDirFileName)) { FilesInDir filesInDir; result = false; - sprintf(filenameBuffer, "%s%s", iBasePath.c_str(), pDirFileName.c_str()); - FILE* df = fopen(filenameBuffer, "rb"); + std::string fb = iBasePath + pDirFileName; + //sprintf(filenameBuffer, "%s%s", iBasePath.c_str(), pDirFileName.c_str()); + //FILE* df = fopen(filenameBuffer, "rb"); + FILE* df = fopen(fb.c_str(), "rb"); if(df) { char lineBuffer[FILENAMEBUFFER_SIZE]; @@ -726,7 +735,7 @@ namespace VMAP filesInDir.incRefCount(); } } - delete [] filenameBuffer; + //delete [] filenameBuffer; return (result); } From 287ec91d734371bd230431dfa82998372096b356 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Thu, 27 Nov 2008 16:26:27 +0300 Subject: [PATCH 116/256] Fixed compile error --- src/game/Creature.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index ad22f6d84..256cad7d8 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -266,7 +266,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) From f3f8549cc3ddadea8e0508d742e91e8b78bcec2c Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Fri, 28 Nov 2008 18:14:31 +0300 Subject: [PATCH 117/256] Updated comment --- src/game/Group.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/Group.h b/src/game/Group.h index f19e2bb9f..5148a919f 100644 --- a/src/game/Group.h +++ b/src/game/Group.h @@ -82,7 +82,7 @@ enum GroupUpdateFlags 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 uint32 spellid + uint8 unk, pet auras... - GROUP_UPDATE_FLAG_UNKNOWN1 = 0x00080000, // uint32, added in WotLK + 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 }; From 91984f83b505398018d4383ede96eff25c78148e Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Fri, 28 Nov 2008 18:34:31 +0300 Subject: [PATCH 118/256] Properly resolved merge conflict --- src/shared/Database/DBCStructure.h | 3 +-- src/shared/Database/DBCfmt.cpp | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index b471353d0..78ae5a67f 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -526,8 +526,7 @@ struct BattlemasterListEntry // 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 { diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 501a7f9fa..8db3016e4 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -23,9 +23,7 @@ const char AreaTriggerEntryfmt[]="niffffffff"; const char BankBagSlotPricesEntryfmt[]="ni"; const char BarberShopStyleEntryfmt[]="nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii"; const char BattlemasterListEntryfmt[]="niiiiiiiiiiiixxxssssssssssssssssxx"; -const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxx"; -// 3*12 new item fields in 3.0.x -//const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; +const char CharStartOutfitEntryfmt[]="diiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char CharTitlesEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi"; const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx"; // ChatChannelsEntryfmt, index not used (more compact store) From 82898a7922cbb7fedd632662b8f3c8f8ee7523d1 Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 28 Nov 2008 22:32:02 +0100 Subject: [PATCH 119/256] Added structure for WorldMapOverlay.dbc --- src/shared/Database/DBCStores.cpp | 4 +++- src/shared/Database/DBCStores.h | 1 + src/shared/Database/DBCStructure.h | 6 ++++++ src/shared/Database/DBCfmt.cpp | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp index 8b35cdd12..72b152e22 100644 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -137,6 +137,7 @@ DBCStorage sVehicleStore(VehicleEntryfmt); DBCStorage sVehicleSeatStore(VehicleSeatEntryfmt); DBCStorage sWorldMapAreaStore(WorldMapAreaEntryfmt); DBCStorage sWorldSafeLocsStore(WorldSafeLocsEntryfmt); +DBCStorage sWorldMapOverlayStore(WorldMapOverlayEntryfmt); typedef std::list StoreProblemList; @@ -188,7 +189,7 @@ void LoadDBCStores(std::string dataPath) { std::string dbcPath = dataPath+"dbc/"; - const uint32 DBCFilesCount = 65; + const uint32 DBCFilesCount = 66; barGoLink bar( DBCFilesCount ); @@ -446,6 +447,7 @@ void LoadDBCStores(std::string dataPath) 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 ) diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h index 58ca5db8c..4650e51ad 100644 --- a/src/shared/Database/DBCStores.h +++ b/src/shared/Database/DBCStores.h @@ -205,6 +205,7 @@ extern DBCStorage sVehicleStore; extern DBCStorage sVehicleSeatStore; //extern DBCStorage sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates extern DBCStorage sWorldSafeLocsStore; +extern DBCStorage sWorldMapOverlayStore; void LoadDBCStores(std::string dataPath); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 78ae5a67f..8c9de62b5 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -1459,6 +1459,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() diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 8db3016e4..4ccbf54c8 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -89,3 +89,5 @@ const char VehicleEntryfmt[]="niffffiiiiiiiiffffiiiiiifffffffffffssssfifi"; const char VehicleSeatEntryfmt[]="niiffffffffffiiiiiifffffffiiifffiiiiiiiffiiiii"; const char WorldMapAreaEntryfmt[]="xinxffffix"; const char WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx"; +const char WorldMapOverlayEntryfmt[]="nxixxxxxxxxxxxxxx"; + From 333146baafb4bcdc94bfa61e7901e19928b93331 Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 28 Nov 2008 23:51:55 +0100 Subject: [PATCH 120/256] Implemented ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA --- src/game/AchievementMgr.cpp | 22 ++++++++++++++++++++++ src/game/Player.cpp | 2 ++ 2 files changed, 24 insertions(+) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index 97c0d51d2..ddc32653f 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -534,6 +534,26 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui ++counter; } SetCriteriaProgress(achievementCriteria, counter); + break; + } + case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA: + { + WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference); + if(!worldOverlayEntry) + break; + + AreaTableEntry const* areaTableEntry = GetAreaEntryByAreaID(worldOverlayEntry->areatableID); + + if(!areaTableEntry) + break; + + uint32 exploreFlag = areaTableEntry->exploreFlag; + uint32 playerIndexOffset = exploreFlag / 32; + uint32 mask = 1<< (exploreFlag % 32); + + if(GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask) + SetCriteriaProgress(achievementCriteria, 1); + break; } } @@ -629,6 +649,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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; // handle all statistic-only criteria here case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 957f259bc..e8ac26fdc 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -5318,6 +5318,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) { From bd3eca6904b9a88fc17c1e9ec2f2b4ead956d352 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 30 Nov 2008 05:17:34 +0300 Subject: [PATCH 121/256] Add and use function for more fast way to get areflag by area id. --- src/game/AchievementMgr.cpp | 10 ++++------ src/shared/Database/DBCStores.cpp | 13 +++++++++++-- src/shared/Database/DBCStores.h | 1 + 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index ddc32653f..e7dc6f3a1 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -542,14 +542,12 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui if(!worldOverlayEntry) break; - AreaTableEntry const* areaTableEntry = GetAreaEntryByAreaID(worldOverlayEntry->areatableID); - - if(!areaTableEntry) + int32 exploreFlag = GetAreaFlagByAreaID(worldOverlayEntry->areatableID); + if(exploreFlag < 0) break; - uint32 exploreFlag = areaTableEntry->exploreFlag; - uint32 playerIndexOffset = exploreFlag / 32; - uint32 mask = 1<< (exploreFlag % 32); + uint32 playerIndexOffset = uint32(exploreFlag) / 32; + uint32 mask = 1<< (uint32(exploreFlag) % 32); if(GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask) SetCriteriaProgress(achievementCriteria, 1); diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp index 72b152e22..d70862eb4 100644 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -524,13 +524,22 @@ uint32 GetTalentSpellCost(uint32 spellId) return 0; } -AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id) +int32 GetAreaFlagByAreaID(uint32 area_id) { AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id); if(i == sAreaFlagByAreaID.end()) + return -1; + + return i->second; +} + +AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id) +{ + int32 areaflag = GetAreaFlagByAreaID(area_id); + if(areaflag < 0) return NULL; - return sAreaStore.LookupEntry(i->second); + return sAreaStore.LookupEntry(areaflag ); } AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag,uint32 map_id) diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h index 4650e51ad..022ce7bbd 100644 --- a/src/shared/Database/DBCStores.h +++ b/src/shared/Database/DBCStores.h @@ -33,6 +33,7 @@ char* GetPetName(uint32 petfamily, uint32 dbclang); uint32 GetTalentSpellCost(uint32 spellId); TalentSpellPos const* GetTalentSpellPos(uint32 spellId); +int32 GetAreaFlagByAreaID(uint32 area_id); // -1 if not found AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id); AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag,uint32 map_id); uint32 GetAreaFlagByMapId(uint32 mapid); From 700d3cf609b76d35642fadf80676bc81221f7a2e Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 30 Nov 2008 13:53:14 +0300 Subject: [PATCH 122/256] Some work on Runic Power and Milling Spell Effect --- .../8_mangos_milling_loot_template.sql | 13 ++ src/game/CharacterHandler.cpp | 50 +++---- src/game/Chat.cpp | 1 + src/game/Chat.h | 1 + src/game/Item.h | 1 + src/game/Level3.cpp | 9 ++ src/game/LootMgr.cpp | 17 +++ src/game/LootMgr.h | 3 + src/game/Player.cpp | 92 +++++++++--- src/game/Player.h | 49 ++++++- src/game/SharedDefines.h | 3 +- src/game/Spell.cpp | 136 +++++++++++++++++- src/game/Spell.h | 3 + src/game/SpellEffects.cpp | 24 +++- src/game/Unit.cpp | 1 + src/game/Unit.h | 1 + src/game/World.cpp | 22 ++- src/game/World.h | 4 +- src/mangosd/mangosd.conf.dist.in | 14 +- src/shared/Database/DBCStructure.h | 11 +- 20 files changed, 379 insertions(+), 76 deletions(-) create mode 100644 sql/wotlk_updates/8_mangos_milling_loot_template.sql diff --git a/sql/wotlk_updates/8_mangos_milling_loot_template.sql b/sql/wotlk_updates/8_mangos_milling_loot_template.sql new file mode 100644 index 000000000..74e7bf2de --- /dev/null +++ b/sql/wotlk_updates/8_mangos_milling_loot_template.sql @@ -0,0 +1,13 @@ +DROP TABLE IF EXISTS `milling_loot_template`; +CREATE TABLE `milling_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 694f3c899..2163e05c5 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -613,15 +613,18 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) if(ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->getClass())) { - 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 ); + 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 ); + } } } @@ -674,7 +677,6 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) pCurrChar->LoadCorpse(); // setting Ghost+speed if dead - //if ( pCurrChar->m_deathState == DEAD ) if (pCurrChar->m_deathState != ALIVE) { // not blizz like, we must correctly save and load player instead... @@ -682,22 +684,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); } @@ -1171,13 +1157,13 @@ void WorldSession::HandleRemoveGlyph( WorldPacket & recv_data ) uint32 slot; recv_data >> slot; - if(slot > 5) - { - sLog.outDebug("Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot); - return; - } + if(slot > 5) + { + sLog.outDebug("Client sent wrong glyph slot number in opcode CMSG_REMOVE_GLYPH %u", slot); + return; + } - if(uint32 glyph = _player->GetGlyph(slot)) + if(uint32 glyph = _player->GetGlyph(slot)) { if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph)) { diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 39c16a4b9..3dcf8dc96 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -258,6 +258,7 @@ ChatCommand * ChatHandler::getCommandTable() { "item_enchantment_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadItemEnchantementsCommand, "", NULL }, { "item_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesItemCommand, "", NULL }, { "mangos_string", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadMangosStringCommand, "", 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 }, diff --git a/src/game/Chat.h b/src/game/Chat.h index 3d4f174f4..c31ae319c 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -225,6 +225,7 @@ 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); diff --git a/src/game/Item.h b/src/game/Item.h index 1580d92d7..de0b0c79c 100644 --- a/src/game/Item.h +++ b/src/game/Item.h @@ -210,6 +210,7 @@ class MANGOS_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(); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 2874a13d8..3c3393876 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -294,6 +294,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`)" ); diff --git a/src/game/LootMgr.cpp b/src/game/LootMgr.cpp index c61e22b7e..0c0804267 100644 --- a/src/game/LootMgr.cpp +++ b/src/game/LootMgr.cpp @@ -39,6 +39,7 @@ LootStore LootTemplates_Disenchant( "disenchant_loot_template", "item disenc 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_Milling( "milling_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"); @@ -1135,6 +1136,21 @@ 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 ) + if(ItemPrototype const* proto = sItemStorage.LookupEntry(i)) + 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; @@ -1227,6 +1243,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 3c5020f53..4d218f2df 100644 --- a/src/game/LootMgr.h +++ b/src/game/LootMgr.h @@ -295,6 +295,7 @@ 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; @@ -305,6 +306,7 @@ void LoadLootTemplates_Creature(); void LoadLootTemplates_Fishing(); void LoadLootTemplates_Gameobject(); void LoadLootTemplates_Item(); +void LoadLootTemplates_Milling(); void LoadLootTemplates_Pickpocketing(); void LoadLootTemplates_Skinning(); void LoadLootTemplates_Disenchant(); @@ -318,6 +320,7 @@ inline void LoadLootTables() LoadLootTemplates_Fishing(); LoadLootTemplates_Gameobject(); LoadLootTemplates_Item(); + LoadLootTemplates_Milling(); LoadLootTemplates_Pickpocketing(); LoadLootTemplates_Skinning(); LoadLootTemplates_Disenchant(); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e8ac26fdc..c4fbbe1b8 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -430,6 +430,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) m_contestedPvPTimer = 0; m_declinedname = NULL; + m_runes = NULL; } Player::~Player () @@ -474,6 +475,7 @@ Player::~Player () itr->second.save->RemovePlayer(this); delete m_declinedname; + delete m_runes; } void Player::CleanupsBeforeDelete() @@ -504,13 +506,6 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, for (int i = 0; i < PLAYER_SLOTS_COUNT; i++) m_items[i] = NULL; - //for(int j = BUYBACK_SLOT_START; j < BUYBACK_SLOT_END; j++) - //{ - // SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1+j*2,0); - // SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1+j,0); - // SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1+j,0); - //} - m_race = race; m_class = class_; @@ -526,9 +521,9 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint8 powertype = cEntry->powerType; - uint32 unitfield; + //uint32 unitfield; - switch(powertype) + /*switch(powertype) { case POWER_ENERGY: case POWER_MANA: @@ -543,10 +538,10 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, 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, 1.5f ); + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); + SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f); switch(gender) { @@ -569,12 +564,12 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint32 RaceClassGender = ( race ) | ( class_ << 8 ) | ( gender << 16 ); SetUInt32Value(UNIT_FIELD_BYTES_0, ( RaceClassGender | ( powertype << 24 ) ) ); - SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield); + //SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield); SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP ); SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE ); SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); // fix cast time showed in spell tooltip on client - //-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))); @@ -586,6 +581,7 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, 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 ); @@ -605,6 +601,8 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, else SetUInt32Value( UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_PLAYER_LEVEL) ); + InitRunes(); + // Played time m_Last_tick = time(NULL); m_Played_time[0] = 0; @@ -626,6 +624,14 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, 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); @@ -1822,14 +1828,17 @@ void Player::RegenerateAll() { RegenerateHealth(); if (!isInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) + { Regenerate(POWER_RAGE); + Regenerate(POWER_RUNIC_POWER); + } } Regenerate( POWER_ENERGY ); Regenerate( POWER_MANA ); - Regenerate( POWER_RUNIC_POWER ); + Regenerate( POWER_RUNE ); m_regenTimer = regenDelay; } @@ -1866,8 +1875,16 @@ void Player::Regenerate(Powers power) addvalue = 20; break; case POWER_RUNIC_POWER: - addvalue = 100; // TODO: find correct regen rate - break; + { + float RunicPowerDecreaseRate = sWorld.getRate(RATE_POWER_RUNICPOWER_LOSS); + addvalue = 30 * RunicPowerDecreaseRate; // 3 RunicPower by tick + } break; + case POWER_RUNE: + { + for(uint32 i = 0; i < 6; ++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; @@ -1883,7 +1900,7 @@ void Player::Regenerate(Powers power) 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) @@ -7217,6 +7234,17 @@ void Player::SendLoot(uint64 guid, LootType loot_type) loot->FillLoot(item->GetEntry(), LootTemplates_Prospecting, this); } } + 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); + } + } else { loot = &item->loot; @@ -7410,8 +7438,8 @@ void Player::SendLoot(uint64 guid, LootType loot_type) 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) @@ -14183,6 +14211,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadDeclinedNames(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES)); + InitRunes(); + m_achievementMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS), holder->GetResult(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS)); m_achievementMgr.CheckAllAchievementCriteria(); return true; @@ -18824,3 +18854,25 @@ void Player::SetTitle(CharTitlesEntry const* title) SetFlag(PLAYER__FIELD_KNOWN_TITLES+fieldIndexOffset, flag); } +void Player::ConvertRune(uint8 index, uint8 newType) +{ + // SMSG_CONVERT_RUNE +} + +void Player::InitRunes() +{ + if(getClass() != CLASS_DEATH_KNIGHT) + return; + + m_runes = new Runes; + + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + SetBaseRune(i, i / 2); + SetCurrentRune(i, i / 2); + SetRuneCooldown(i, 0); + } + + for(uint32 i = 0; i < NUM_RUNES; ++i) + SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f); +} diff --git a/src/game/Player.h b/src/game/Player.h index e265cc4a3..88e576ac1 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -224,6 +224,29 @@ struct Areas float y2; }; +#define MAX_RUNES 6 + +enum RuneType +{ + RUNE_BLOOD = 0, + RUNE_FROST = 1, + RUNE_UNHOLY = 2, + RUNE_DEATH = 3, + NUM_RUNES = 4 +}; + +struct RuneInfo +{ + uint8 BaseRune:1; + uint8 CurrentRune:1; + uint8 Cooldown:1; +}; + +struct Runes +{ + RuneInfo runes[6]; +}; + enum FactionFlags { FACTION_FLAG_VISIBLE = 0x01, // makes visible in client (set or can be set at interaction with target of this faction) @@ -481,7 +504,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 @@ -519,10 +543,10 @@ typedef std::map QuestStatusMap; enum QuestSlotOffsets { - QUEST_ID_OFFSET = 0, - QUEST_STATE_OFFSET = 1, + QUEST_ID_OFFSET = 0, + QUEST_STATE_OFFSET = 1, QUEST_COUNTS_OFFSET = 2, - QUEST_TIME_OFFSET = 3 + QUEST_TIME_OFFSET = 3 }; #define MAX_QUEST_OFFSET 4 @@ -2067,7 +2091,21 @@ class MANGOS_DLL_SPEC Player : public Unit WorldLocation& GetTeleportDest() { return m_teleport_dest; } DeclinedName const* GetDeclinedNames() const { return m_declinedname; } - + RuneInfo const* GetRuneInfo(uint8 index) { return &m_runes->runes[index]; } + uint8 GetBaseRune(uint8 index) { return m_runes->runes[index].BaseRune; } + uint8 GetCurrentRune(uint8 index) { return m_runes->runes[index].CurrentRune; } + uint8 GetRuneCooldown(uint8 index) { return m_runes->runes[index].Cooldown; } + void SetRuneInfo(uint8 index, uint8 baseRune, uint8 currentRune, uint8 cooldown) + { + m_runes->runes[index].BaseRune = baseRune; + m_runes->runes[index].CurrentRune = currentRune; + m_runes->runes[index].Cooldown = cooldown; + } + void SetBaseRune(uint8 index, uint8 baseRune) { m_runes->runes[index].BaseRune = baseRune; } + void SetCurrentRune(uint8 index, uint8 currentRune) { m_runes->runes[index].BaseRune = currentRune; } + void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].BaseRune = cooldown; } + void ConvertRune(uint8 index, uint8 newType); + void InitRunes(); AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } bool HasTitle(uint32 bitIndex); bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); } @@ -2302,6 +2340,7 @@ class MANGOS_DLL_SPEC Player : public Unit WorldLocation m_teleport_dest; DeclinedName *m_declinedname; + Runes *m_runes; AchievementMgr m_achievementMgr; private: // internal common parts for CanStore/StoreItem functions diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 38fc9b959..a07863544 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -664,7 +664,7 @@ enum SpellEffects SPELL_EFFECT_155 = 155, SPELL_EFFECT_156 = 156, SPELL_EFFECT_157 = 157, - SPELL_EFFECT_158 = 158, + SPELL_EFFECT_MILLING = 158, SPELL_EFFECT_159 = 159, TOTAL_SPELL_EFFECTS = 160 }; @@ -1817,6 +1817,7 @@ inline uint32 SkillByQuestSort(int32 QuestSort) 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; } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index f2a858dfc..7420e985d 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -593,6 +593,7 @@ void Spell::FillTargetMap() 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; @@ -3115,6 +3116,12 @@ void Spell::TakePower() Powers powerType = Powers(m_spellInfo->powerType); + if(powerType == POWER_RUNE) + { + TakeRunePower(); + return; + } + m_caster->ModifyPower(powerType, -(int32)m_powerCost); // Set the five second timer @@ -3122,6 +3129,105 @@ void Spell::TakePower() m_caster->SetLastManaUse(getMSTime()); } +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_RUNES]; // 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) + if(!plr->GetRuneCooldown(i)) + runeCost[plr->GetCurrentRune(i)]--; + + 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_REAGENTS; // 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; + + int32 runeCost[NUM_RUNES]; // 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) + { + if(!plr->GetRuneCooldown(i)) + { + uint8 rune = plr->GetCurrentRune(i); + if(runeCost[rune] > 0) + { + plr->SetRuneCooldown(i, 5); // 5*2=10 sec + runeCost[rune]--; + } + } + } + + runeCost[RUNE_DEATH] = runeCost[RUNE_BLOOD] + runeCost[RUNE_FROST] + runeCost[RUNE_UNHOLY]; + + if(runeCost[RUNE_DEATH] > 0) + { + for(uint32 i = 0; i < MAX_RUNES; ++i) + { + if(!plr->GetRuneCooldown(i) && plr->GetCurrentRune(i) == RUNE_DEATH) + { + plr->SetRuneCooldown(i, 5); // 5*2=10 sec + runeCost[plr->GetCurrentRune(i)]--; + uint8 base = plr->GetBaseRune(i); + plr->SetCurrentRune(i, base); + plr->ConvertRune(i, base); + if(runeCost[RUNE_DEATH] == 0) + break; + } + } + } + + float rp = src->runePowerGain;; + rp *= sWorld.getRate(RATE_POWER_RUNICPOWER_INCOME); + rp += plr->GetPower(POWER_RUNIC_POWER); + plr->SetPower(POWER_RUNIC_POWER, (uint32)rp); +} + void Spell::TakeReagents() { if(m_IsTriggeredSpell) // reagents used in triggered spell removed by original spell or don't must be removed. @@ -4040,7 +4146,7 @@ uint8 Spell::CanCast(bool strict) 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; @@ -4431,6 +4537,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) @@ -4710,6 +4821,29 @@ uint8 Spell::CheckItems() 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: { diff --git a/src/game/Spell.h b/src/game/Spell.h index b52f503ef..7aaf0b87c 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -276,6 +276,7 @@ class Spell void EffectSkinning(uint32 i); void EffectCharge(uint32 i); void EffectProspecting(uint32 i); + void EffectMilling(uint32 i); void EffectSendTaxi(uint32 i); void EffectSummonCritter(uint32 i); void EffectKnockBack(uint32 i); @@ -311,6 +312,8 @@ class Spell void cast(bool skipCheck = false); void finish(bool ok = true); void TakePower(); + uint8 CheckRuneCost(uint32 runeCostID); + void TakeRunePower(); void TakeReagents(); void TakeCastItem(); void TriggerSpell(); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 6742886f3..2e101b6db 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -214,7 +214,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectNULL, //155 Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal. &Spell::EffectNULL, //156 Add Socket &Spell::EffectNULL, //157 create/learn random item/spell for profession - &Spell::EffectNULL, //158 milling + &Spell::EffectMilling, //158 milling &Spell::EffectNULL //159 allow rename pet once again }; @@ -6114,6 +6114,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"); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index d57948e5b..95b4cee7c 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -2066,6 +2066,7 @@ void Unit::DoAttackDamage (Unit *pVictim, uint32 *damage, CleanDamage *cleanDama { case CLASS_WARRIOR: case CLASS_ROGUE: + case CLASS_DEATH_KNIGHT: maxLowEnd = 0.91; //If the attacker is a melee class then instead the lower value of 0.91 } diff --git a/src/game/Unit.h b/src/game/Unit.h index 289317472..63cfd77da 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -144,6 +144,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, diff --git a/src/game/World.cpp b/src/game/World.cpp index 86a026a4d..912b182f0 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -406,24 +406,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); @@ -630,10 +636,11 @@ void World::LoadConfigSettings(bool reload) } else m_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfig.GetIntDefault("MaxPlayerLevel", 60); - if(m_configs[CONFIG_MAX_PLAYER_LEVEL] > 255) + + if(m_configs[CONFIG_MAX_PLAYER_LEVEL] > 100) { - sLog.outError("MaxPlayerLevel (%i) must be in range 1..255. Set to 255.",m_configs[CONFIG_MAX_PLAYER_LEVEL]); - m_configs[CONFIG_MAX_PLAYER_LEVEL] = 255; + sLog.outError("MaxPlayerLevel (%i) must be in range 1..100. Set to 100.",m_configs[CONFIG_MAX_PLAYER_LEVEL]); + m_configs[CONFIG_MAX_PLAYER_LEVEL] = 100; } m_configs[CONFIG_START_PLAYER_LEVEL] = sConfig.GetIntDefault("StartPlayerLevel", 1); @@ -703,6 +710,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) diff --git a/src/game/World.h b/src/game/World.h index 0b2693ba1..3821be4fe 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -168,6 +168,7 @@ enum WorldConfigs CONFIG_LISTEN_RANGE_SAY, CONFIG_LISTEN_RANGE_TEXTEMOTE, CONFIG_LISTEN_RANGE_YELL, + CONFIG_SKILL_MILLING, CONFIG_VALUE_COUNT }; @@ -178,6 +179,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, @@ -221,7 +224,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, diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 7faddd8c4..554e3cfaf 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -505,7 +505,12 @@ LogColors = "" # Default: 3600 sec (1 hour) # # SkillChance.Prospecting -# For prospecting skillup not possible by default, but can be allowed as custom setting +# 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 # @@ -555,6 +560,7 @@ MinPetitionSigns = 9 MaxGroupXPDistance = 74 MailDeliveryDelay = 3600 SkillChance.Prospecting = 0 +SkillChance.Milling = 0 Event.Announce = 0 BeepAtStart = 1 Motd = "Welcome to the Massive Network Game Object Server." @@ -862,8 +868,9 @@ Visibility.Distance.Grey.Object = 10 # 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 # @@ -984,8 +991,9 @@ 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 diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 8c9de62b5..b42d9c223 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -1194,11 +1194,12 @@ struct SpellRangeEntry struct SpellRuneCostEntry { - uint32 ID; - uint32 bloodRuneCost; - uint32 frostRuneCost; - uint32 unholyRuneCost; - uint32 runePowerGain; + 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 From 59fb246652610bcb1c1b10561f49ad4f66b4fb0b Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 30 Nov 2008 14:12:24 +0300 Subject: [PATCH 123/256] Limit max player level to 100 --- src/game/World.cpp | 38 ++++++++++++++++---------------- src/mangosd/mangosd.conf.dist.in | 4 ++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/game/World.cpp b/src/game/World.cpp index ea6cdd9c6..0b5d476be 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -744,30 +744,30 @@ 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_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_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState", 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_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]) { - sLog.outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..255. Set to %u.", - m_configs[CONFIG_START_GM_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL]); + sLog.outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..100. Set to %u.", + m_configs[CONFIG_START_GM_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL], m_configs[CONFIG_START_PLAYER_LEVEL]); m_configs[CONFIG_START_GM_LEVEL] = m_configs[CONFIG_START_PLAYER_LEVEL]; } - else if(m_configs[CONFIG_START_GM_LEVEL] > 255) + else if(m_configs[CONFIG_START_GM_LEVEL] > 100) { - sLog.outError("GM.StartLevel (%i) must be in range 1..255. Set to %u.",m_configs[CONFIG_START_GM_LEVEL],255); - m_configs[CONFIG_START_GM_LEVEL] = 255; + sLog.outError("GM.StartLevel (%i) must be in range 1..100. Set to %u.", m_configs[CONFIG_START_GM_LEVEL], 100); + m_configs[CONFIG_START_GM_LEVEL] = 100; } m_configs[CONFIG_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode",0); @@ -859,13 +859,13 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_WORLD_BOSS_LEVEL_DIFF] = sConfig.GetIntDefault("WorldBossLevelDiff",3); - // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level (255) - m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.LowLevelHideDiff",4); - if(m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > 255) - m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = 255; - m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.HighLevelHideDiff",7); - if(m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > 255) - m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = 255; + // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level (100) + m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.LowLevelHideDiff", 4); + if(m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > 100) + m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = 100; + m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.HighLevelHideDiff", 7); + if(m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > 100) + m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = 100; m_configs[CONFIG_DETECT_POS_COLLISION] = sConfig.GetBoolDefault("DetectPosCollision", true); diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 59da7deff..0bda27130 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -415,7 +415,7 @@ LogColors = "" # 2 - disable intro show in all cases # # MaxPlayerLevel -# Max level that can be reached by player for experience (in range from 1 to 255). +# Max level that can be reached by player for experience (in range from 1 to 100). # Change not recommended # Default: 70 # @@ -843,7 +843,7 @@ Channel.SilentlyGMJoin = 0 # 0 (not include) # # GM.StartLevel -# GM starting level (1-255) +# GM starting level (1-100) # Default: 1 # ################################################################################################################### From 54c1585cdf0b524902ed9f945d2969237b69ea38 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 30 Nov 2008 14:59:35 +0300 Subject: [PATCH 124/256] Small fix --- src/game/Player.cpp | 8 ++++---- src/game/Player.h | 13 +++++++------ src/game/Spell.cpp | 12 ++++++------ 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 5fd97a769..f5f4bc45b 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18896,11 +18896,11 @@ void Player::InitRunes() for(uint32 i = 0; i < MAX_RUNES; ++i) { - SetBaseRune(i, i / 2); - SetCurrentRune(i, i / 2); - SetRuneCooldown(i, 0); + SetBaseRune(i, i / 2); // init base types + SetCurrentRune(i, i / 2); // init current types + SetRuneCooldown(i, 0); // reset cooldowns } - for(uint32 i = 0; i < NUM_RUNES; ++i) + for(uint32 i = 0; i < NUM_RUNE_TYPES; ++i) SetFloatValue(PLAYER_RUNE_REGEN_1 + i, 0.1f); } diff --git a/src/game/Player.h b/src/game/Player.h index 7f1844e96..f46b8796e 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -224,15 +224,16 @@ struct Areas float y2; }; -#define MAX_RUNES 6 +#define MAX_RUNES 6 +#define RUNE_COOLDOWN 5 // 5*2=10 sec enum RuneType { - RUNE_BLOOD = 0, - RUNE_FROST = 1, - RUNE_UNHOLY = 2, - RUNE_DEATH = 3, - NUM_RUNES = 4 + RUNE_BLOOD = 0, + RUNE_FROST = 1, + RUNE_UNHOLY = 2, + RUNE_DEATH = 3, + NUM_RUNE_TYPES = 4 }; struct RuneInfo diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 4ee734d57..e1646f14e 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3157,7 +3157,7 @@ uint8 Spell::CheckRuneCost(uint32 runeCostID) if(src->NoRuneCost()) return 0; - int32 runeCost[NUM_RUNES]; // blood, frost, unholy, death + int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death for(uint32 i = 0; i < RUNE_DEATH; ++i) runeCost[i] = src->RuneCost[i]; @@ -3193,7 +3193,7 @@ void Spell::TakeRunePower() if(!src || (src->NoRuneCost() && src->NoRunicPowerGain())) return; - int32 runeCost[NUM_RUNES]; // blood, frost, unholy, death + int32 runeCost[NUM_RUNE_TYPES]; // blood, frost, unholy, death for(uint32 i = 0; i < RUNE_DEATH; ++i) runeCost[i] = src->RuneCost[i]; @@ -3207,7 +3207,7 @@ void Spell::TakeRunePower() uint8 rune = plr->GetCurrentRune(i); if(runeCost[rune] > 0) { - plr->SetRuneCooldown(i, 5); // 5*2=10 sec + plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec runeCost[rune]--; } } @@ -3221,7 +3221,7 @@ void Spell::TakeRunePower() { if(!plr->GetRuneCooldown(i) && plr->GetCurrentRune(i) == RUNE_DEATH) { - plr->SetRuneCooldown(i, 5); // 5*2=10 sec + plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec runeCost[plr->GetCurrentRune(i)]--; uint8 base = plr->GetBaseRune(i); plr->SetCurrentRune(i, base); @@ -3232,10 +3232,10 @@ void Spell::TakeRunePower() } } + // you can gain some runic power when use runes float rp = src->runePowerGain;; rp *= sWorld.getRate(RATE_POWER_RUNICPOWER_INCOME); - rp += plr->GetPower(POWER_RUNIC_POWER); - plr->SetPower(POWER_RUNIC_POWER, (uint32)rp); + plr->ModifyPower(POWER_RUNIC_POWER, (int32)rp) } void Spell::TakeReagents() From 0e0d7212924b76054979173fb92a88e6a1f7353b Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 30 Nov 2008 16:16:00 +0300 Subject: [PATCH 125/256] AuraConvertRune, EffectActivateRune, dunno if it's correct way to do that... --- src/game/Player.cpp | 1 + src/game/SharedDefines.h | 2 +- src/game/SpellAuraDefines.h | 2 +- src/game/SpellAuras.cpp | 37 ++++++++++++++++++++++++++++++++++++- src/game/SpellAuras.h | 1 + src/game/SpellEffects.cpp | 21 ++++++++++++++++++++- 6 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index f5f4bc45b..d2783886e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18884,6 +18884,7 @@ void Player::SetTitle(CharTitlesEntry const* title) void Player::ConvertRune(uint8 index, uint8 newType) { + SetCurrentRune(index, newType); // SMSG_CONVERT_RUNE } diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index a07863544..04452f02f 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -652,7 +652,7 @@ enum SpellEffects SPELL_EFFECT_APPLY_AREA_AURA_OWNER = 143, SPELL_EFFECT_144 = 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, diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 6d744df6b..cd16eca68 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -291,7 +291,7 @@ enum AuraType SPELL_AURA_246 = 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, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 713e04801..adc1690c0 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -299,7 +299,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleUnused, //246 unused &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::HandleNULL, //252 @@ -6365,3 +6365,38 @@ void Aura::HandleAuraControlVehicle(bool apply, bool Real) WorldPacket data(SMSG_SHOW_VEHICLE_UI, 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; + } + } + } +} diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index e6ebff7ec..6df6e7a10 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -208,6 +208,7 @@ class MANGOS_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); virtual ~Aura(); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 2e101b6db..ed6c0e295 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -202,7 +202,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectApplyAreaAura, //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER &Spell::EffectNULL, //144 SPELL_EFFECT_144 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 @@ -6282,3 +6282,22 @@ void Spell::EffectQuestFail(uint32 i) ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]); } + +void Spell::EffectActivateRune(uint32 i) +{ + 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[i]) + { + plr->SetRuneCooldown(j, 0)); + } + } +} From e556b67ddc544d077f0c1ba508d5dd7b5e9cd29f Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 30 Nov 2008 17:04:36 +0300 Subject: [PATCH 126/256] Fixed compile errors --- src/game/Spell.cpp | 2 +- src/game/Spell.h | 1 + src/game/SpellEffects.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index e1646f14e..846a51cb4 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3235,7 +3235,7 @@ void Spell::TakeRunePower() // 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) + plr->ModifyPower(POWER_RUNIC_POWER, (int32)rp); } void Spell::TakeReagents() diff --git a/src/game/Spell.h b/src/game/Spell.h index 7aaf0b87c..d14293cde 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -302,6 +302,7 @@ class Spell void EffectTriggerRitualOfSummoning(uint32 i); void EffectKillCredit(uint32 i); void EffectQuestFail(uint32 i); + void EffectActivateRune(uint32 i); Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL ); ~Spell(); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index ed6c0e295..cf290bfe8 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -6297,7 +6297,7 @@ void Spell::EffectActivateRune(uint32 i) { if(plr->GetRuneCooldown(j) && plr->GetCurrentRune(j) == m_spellInfo->EffectMiscValue[i]) { - plr->SetRuneCooldown(j, 0)); + plr->SetRuneCooldown(j, 0); } } } From d238187adde34d352b78a5601cd886288fc2fce7 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 30 Nov 2008 21:18:33 +0300 Subject: [PATCH 127/256] Fixed typos --- src/game/Player.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/Player.h b/src/game/Player.h index f46b8796e..f72190878 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2103,8 +2103,8 @@ class MANGOS_DLL_SPEC Player : public Unit m_runes->runes[index].Cooldown = cooldown; } void SetBaseRune(uint8 index, uint8 baseRune) { m_runes->runes[index].BaseRune = baseRune; } - void SetCurrentRune(uint8 index, uint8 currentRune) { m_runes->runes[index].BaseRune = currentRune; } - void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].BaseRune = cooldown; } + void SetCurrentRune(uint8 index, uint8 currentRune) { m_runes->runes[index].currentRune = currentRune; } + void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].cooldown = cooldown; } void ConvertRune(uint8 index, uint8 newType); void InitRunes(); AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } From cb09bd72d3b28bc2e339fc25bb5f766f6ecf3ef7 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sun, 30 Nov 2008 21:21:16 +0300 Subject: [PATCH 128/256] Fixed typos2 --- src/game/Player.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/Player.h b/src/game/Player.h index f72190878..4166238fc 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2103,8 +2103,8 @@ class MANGOS_DLL_SPEC Player : public Unit m_runes->runes[index].Cooldown = 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; } + void SetCurrentRune(uint8 index, uint8 currentRune) { m_runes->runes[index].CurrentRune = currentRune; } + void SetRuneCooldown(uint8 index, uint8 cooldown) { m_runes->runes[index].Cooldown = cooldown; } void ConvertRune(uint8 index, uint8 newType); void InitRunes(); AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } From 60b8f30898875a1e25e4617df80c6da9f184f58e Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 1 Dec 2008 08:19:26 +0300 Subject: [PATCH 129/256] Rune system fix, dk crash fix --- src/game/AchievementMgr.cpp | 1 - src/game/Player.cpp | 7 +++---- src/game/Player.h | 19 ++++++------------ src/game/Spell.cpp | 39 +++++++++++++++++++++++-------------- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index e7dc6f3a1..c255bfb93 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -839,4 +839,3 @@ void AchievementMgr::BuildAllDataPacket(WorldPacket *data) *data << int32(-1); } - diff --git a/src/game/Player.cpp b/src/game/Player.cpp index d2783886e..cddb31692 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1890,9 +1890,9 @@ void Player::Regenerate(Powers power) } break; case POWER_RUNE: { - for(uint32 i = 0; i < 6; ++i) + 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) + SetRuneCooldown(i, cd - 1); // ... by 2 sec (because update is every 2 sec) } break; case POWER_FOCUS: case POWER_HAPPINESS: @@ -14083,6 +14083,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) InitStatsForLevel(); InitTaxiNodesForLevel(); InitGlyphsForLevel(); + InitRunes(); // apply original stats mods before spell loading or item equipment that call before equip _RemoveStatsMods() @@ -14239,8 +14240,6 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadDeclinedNames(holder->GetResult(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES)); - InitRunes(); - m_achievementMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACHIEVEMENTS), holder->GetResult(PLAYER_LOGIN_QUERY_LOADCRITERIAPROGRESS)); m_achievementMgr.CheckAllAchievementCriteria(); return true; diff --git a/src/game/Player.h b/src/game/Player.h index 4166238fc..6e1537579 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -238,9 +238,9 @@ enum RuneType struct RuneInfo { - uint8 BaseRune:1; - uint8 CurrentRune:1; - uint8 Cooldown:1; + uint8 BaseRune; + uint8 CurrentRune; + uint8 Cooldown; }; struct Runes @@ -2092,16 +2092,9 @@ class MANGOS_DLL_SPEC Player : public Unit WorldLocation& GetTeleportDest() { return m_teleport_dest; } DeclinedName const* GetDeclinedNames() const { return m_declinedname; } - RuneInfo const* GetRuneInfo(uint8 index) { return &m_runes->runes[index]; } - uint8 GetBaseRune(uint8 index) { return m_runes->runes[index].BaseRune; } - uint8 GetCurrentRune(uint8 index) { return m_runes->runes[index].CurrentRune; } - uint8 GetRuneCooldown(uint8 index) { return m_runes->runes[index].Cooldown; } - void SetRuneInfo(uint8 index, uint8 baseRune, uint8 currentRune, uint8 cooldown) - { - m_runes->runes[index].BaseRune = baseRune; - m_runes->runes[index].CurrentRune = currentRune; - m_runes->runes[index].Cooldown = cooldown; - } + 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; } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 846a51cb4..337273e21 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3160,20 +3160,31 @@ uint8 Spell::CheckRuneCost(uint32 runeCostID) 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) - if(!plr->GetRuneCooldown(i)) - runeCost[plr->GetCurrentRune(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_REAGENTS; // not sure if result code is correct + return SPELL_FAILED_NO_POWER; // not sure if result code is correct return 0; } @@ -3196,20 +3207,19 @@ void Spell::TakeRunePower() 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) { - if(!plr->GetRuneCooldown(i)) + uint8 rune = plr->GetCurrentRune(i); + if((plr->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0)) { - uint8 rune = plr->GetCurrentRune(i); - if(runeCost[rune] > 0) - { - plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec - runeCost[rune]--; - } + plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec + runeCost[rune]--; } } @@ -3219,13 +3229,12 @@ void Spell::TakeRunePower() { for(uint32 i = 0; i < MAX_RUNES; ++i) { - if(!plr->GetRuneCooldown(i) && plr->GetCurrentRune(i) == RUNE_DEATH) + uint8 rune = plr->GetCurrentRune(i); + if((plr->GetRuneCooldown(i) == 0) && (rune == RUNE_DEATH)) { plr->SetRuneCooldown(i, RUNE_COOLDOWN); // 5*2=10 sec - runeCost[plr->GetCurrentRune(i)]--; - uint8 base = plr->GetBaseRune(i); - plr->SetCurrentRune(i, base); - plr->ConvertRune(i, base); + runeCost[rune]--; + plr->ConvertRune(i, plr->GetBaseRune(i)); if(runeCost[RUNE_DEATH] == 0) break; } From b37ccbd08b136610abbf5ab707aa3190f422afa1 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 1 Dec 2008 19:31:47 +0300 Subject: [PATCH 130/256] Rune cooldowns, still bugged for some unknown reason :( --- src/game/Object.h | 2 -- src/game/Player.cpp | 27 ++++++++++++++++- src/game/Player.h | 18 ++++++++++-- src/game/Spell.cpp | 71 +++++++++++++++++++++++++++++++-------------- src/game/Spell.h | 20 +++++++++++-- 5 files changed, 107 insertions(+), 31 deletions(-) diff --git a/src/game/Object.h b/src/game/Object.h index e65f14d43..974e6b0b3 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -241,8 +241,6 @@ class MANGOS_DLL_SPEC Object { ASSERT( index < m_valuesCount || PrintIndexError( index , false ) ); ASSERT( offset < 4 ); - //return *(((uint16*)&m_uint32Values[ index ])+offset); - //return (((uint8*)m_uint32Values[index])[offset] & flag) != 0; return (((uint8*)&m_uint32Values[index])[offset] & flag) != 0; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index b19d90096..fd7ca3b9d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18899,7 +18899,29 @@ void Player::SetTitle(CharTitlesEntry const* title) void Player::ConvertRune(uint8 index, uint8 newType) { SetCurrentRune(index, newType); - // SMSG_CONVERT_RUNE + + 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() @@ -18909,11 +18931,14 @@ void Player::InitRunes() 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) diff --git a/src/game/Player.h b/src/game/Player.h index bd6d63c39..2682149f6 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -230,8 +230,8 @@ struct Areas enum RuneType { RUNE_BLOOD = 0, - RUNE_FROST = 1, - RUNE_UNHOLY = 2, + RUNE_UNHOLY = 1, + RUNE_FROST = 2, RUNE_DEATH = 3, NUM_RUNE_TYPES = 4 }; @@ -246,6 +246,15 @@ struct RuneInfo struct Runes { RuneInfo runes[6]; + 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 @@ -2092,13 +2101,16 @@ class MANGOS_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; } + 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); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 337273e21..509f9d389 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -346,6 +346,7 @@ Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 origi else m_autoRepeat = false; + 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 @@ -2652,6 +2653,9 @@ void Spell::SendSpellStart() if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; + if(m_runesState) + castFlags |= CAST_FLAG_UNKNOWN10; + Unit *target; if(!m_targets.getUnitTarget()) target = m_caster; @@ -2672,19 +2676,26 @@ void Spell::SendSpellStart() m_targets.write(&data); - if ( castFlags & CAST_FLAG_UNKNOWN6 ) + if ( castFlags & CAST_FLAG_UNKNOWN6 ) // predicted power? data << uint32(0); - if ( castFlags & CAST_FLAG_UNKNOWN7 ) + if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns { - uint8 v1 = 0; - uint8 v2 = 0; - data << v1; // v1 - data << v2; // v2 - for(uint8 i = 0; i < 6; ++i) - if((1 << i) & v1) - if(!(1 << i) & v2) - data << uint8(0); + 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 ) @@ -2709,7 +2720,14 @@ void Spell::SendSpellGo() uint32 castFlags = CAST_FLAG_UNKNOWN3; if(IsRangedSpell()) - castFlags |= CAST_FLAG_AMMO; + castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual + + if(m_runesState) + { + castFlags |= CAST_FLAG_UNKNOWN10; // same as in SMSG_SPELL_START + castFlags |= CAST_FLAG_UNKNOWN6; // makes cooldowns visible + castFlags |= CAST_FLAG_UNKNOWN7; // rune cooldowns + } WorldPacket data(SMSG_SPELL_GO, 50); // guess size if(m_CastItem) @@ -2727,19 +2745,26 @@ void Spell::SendSpellGo() m_targets.write(&data); - if ( castFlags & CAST_FLAG_UNKNOWN6 ) // unknown wotlk + if ( castFlags & CAST_FLAG_UNKNOWN6 ) // unknown wotlk, predicted power? data << uint32(0); - if ( castFlags & CAST_FLAG_UNKNOWN7 ) + if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns? { - uint8 v1 = 0; - uint8 v2 = 0; - data << v1; // v1 - data << v2; // v2 - for(uint8 i = 0; i < 6; ++i) - if((1 << i) & v1) - if(!(1 << i) & v2) - data << uint8(0); + 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 @@ -3204,6 +3229,8 @@ void Spell::TakeRunePower() 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) @@ -3223,7 +3250,7 @@ void Spell::TakeRunePower() } } - runeCost[RUNE_DEATH] = runeCost[RUNE_BLOOD] + runeCost[RUNE_FROST] + runeCost[RUNE_UNHOLY]; + runeCost[RUNE_DEATH] = runeCost[RUNE_BLOOD] + runeCost[RUNE_UNHOLY] + runeCost[RUNE_FROST]; if(runeCost[RUNE_DEATH] > 0) { diff --git a/src/game/Spell.h b/src/game/Spell.h index d14293cde..ac71da5b4 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -67,16 +67,29 @@ enum SpellCastTargetFlags 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_AMMO = 0x00000020, // Projectiles visual CAST_FLAG_UNKNOWN8 = 0x00000040, CAST_FLAG_UNKNOWN9 = 0x00000080, CAST_FLAG_UNKNOWN3 = 0x00000100, - CAST_FLAG_UNKNOWN6 = 0x00000800, // wotlk + 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_UNKNOWN7 = 0x00200000 // wotlk + CAST_FLAG_UNKNOWN20 = 0x00100000, + CAST_FLAG_UNKNOWN7 = 0x00200000 // wotlk, rune cooldown list }; enum SpellNotifyPushType @@ -436,6 +449,7 @@ 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; } From 84f43e60abdc9f3a779dd5a66c258c54b85f7fcd Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Tue, 2 Dec 2008 15:20:10 +0300 Subject: [PATCH 131/256] Fixed crash --- src/game/Player.cpp | 6 ++++-- src/game/Spell.cpp | 29 ++++++++--------------------- src/mangosd/RASocket.h | 2 +- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index fd7ca3b9d..889a55b48 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1839,7 +1839,8 @@ void Player::RegenerateAll() if (!isInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) { Regenerate(POWER_RAGE); - Regenerate(POWER_RUNIC_POWER); + if(getClass() == CLASS_DEATH_KNIGHT) + Regenerate(POWER_RUNIC_POWER); } } @@ -1847,7 +1848,8 @@ void Player::RegenerateAll() Regenerate( POWER_MANA ); - Regenerate( POWER_RUNE ); + if(getClass() == CLASS_DEATH_KNIGHT) + Regenerate( POWER_RUNE ); m_regenTimer = regenDelay; } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 509f9d389..a0b48bb8a 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -219,7 +219,7 @@ void SpellCastTargets::write ( WorldPacket * data ) { *data << uint32(m_targetMask); - if( m_targetMask & ( TARGET_FLAG_UNIT | TARGET_FLAG_PVP_CORPSE | TARGET_FLAG_OBJECT | TARGET_FLAG_CORPSE | TARGET_FLAG_UNK2 ) ) + if( m_targetMask & ( TARGET_FLAG_UNIT | TARGET_FLAG_PVP_CORPSE | TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK | TARGET_FLAG_CORPSE | TARGET_FLAG_UNK2 ) ) { if(m_targetMask & TARGET_FLAG_UNIT) { @@ -2633,13 +2633,6 @@ void Spell::SendCastResult(uint8 result) } ((Player*)m_caster)->GetSession()->SendPacket(&data); } - /*else - { - WorldPacket data(SMSG_CLEAR_EXTRA_AURA_INFO_OBSOLETE, (8+4)); - data.append(m_caster->GetPackGUID()); - data << uint32(m_spellInfo->Id); - ((Player*)m_caster)->GetSession()->SendPacket(&data); - }*/ } void Spell::SendSpellStart() @@ -2653,14 +2646,10 @@ void Spell::SendSpellStart() if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; - if(m_runesState) + if(m_spellInfo->runeCostID) castFlags |= CAST_FLAG_UNKNOWN10; - Unit *target; - if(!m_targets.getUnitTarget()) - target = m_caster; - else - target = m_targets.getUnitTarget(); + Unit *target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster; WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); if(m_CastItem) @@ -2701,6 +2690,7 @@ void Spell::SendSpellStart() if ( castFlags & CAST_FLAG_AMMO ) WriteAmmoToPacket(&data); + data.hexlike(); m_caster->SendMessageToSet(&data, true); } @@ -2710,19 +2700,15 @@ void Spell::SendSpellGo() if(!IsNeedSendToClient()) return; - sLog.outDebug("Sending SMSG_SPELL_GO id=%u",m_spellInfo->Id); + sLog.outDebug("Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id); - Unit * target; - if(!m_targets.getUnitTarget()) - target = m_caster; - else - target = m_targets.getUnitTarget(); + Unit *target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster; uint32 castFlags = CAST_FLAG_UNKNOWN3; if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual - if(m_runesState) + if(m_spellInfo->runeCostID) { castFlags |= CAST_FLAG_UNKNOWN10; // same as in SMSG_SPELL_START castFlags |= CAST_FLAG_UNKNOWN6; // makes cooldowns visible @@ -2787,6 +2773,7 @@ void Spell::SendSpellGo() data << uint8(0); } + data.hexlike(); m_caster->SendMessageToSet(&data, true); } diff --git a/src/mangosd/RASocket.h b/src/mangosd/RASocket.h index fe539af65..d9acb8284 100644 --- a/src/mangosd/RASocket.h +++ b/src/mangosd/RASocket.h @@ -50,7 +50,7 @@ class RASocket: public TcpSocket bool bLog; bool bSecure; //kick on wrong pass, non exist. user, user with no priv //will protect from DOS, bruteforce attacks - //some 'smart' protection must be added for more scurity + //some 'smart' protection must be added for more security uint8 iMinLevel; enum { From 0dbc77a628fc2ac8498c80f5105f518166fa3a6e Mon Sep 17 00:00:00 2001 From: arrai Date: Tue, 2 Dec 2008 14:44:31 +0100 Subject: [PATCH 132/256] Added support for large server to client packets. SMSG_RESPOND_INSPECT_ACHIEVEMENTS and SMSG_ALL_ACHIEVEMENT_DATA have a good chance of reaching the old 32767 byte limit. --- src/game/WorldSocket.cpp | 58 +++++++++++++++++++++++++++-------- src/shared/Auth/AuthCrypt.cpp | 3 +- src/shared/Auth/AuthCrypt.h | 1 - 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/src/game/WorldSocket.cpp b/src/game/WorldSocket.cpp index 8cd7c423c..8c246cf9c 100644 --- a/src/game/WorldSocket.cpp +++ b/src/game/WorldSocket.cpp @@ -52,8 +52,48 @@ 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= new uint8[5]; + header[headerIndex++] = 0x80|(0xFF &(size>>16)); + } + else + { + header= new uint8[4]; + } + + header[headerIndex++] = 0xFF &(size>>8); + header[headerIndex++] = 0xFF &size; + + header[headerIndex++] = 0xFF & cmd; + header[headerIndex++] = 0xFF & (cmd>>8); + } + + ~ServerPktHeader() + { + delete[] header; + } + + uint8 getHeaderLength() + { + // cmd = 2 bytes, size= 2||3bytes + return 2+(isLargePacket()?3:2); + } + + bool isLargePacket() + { + return size > 0x7FFF; + } + + const uint32 size; + uint8 *header; }; struct ClientPktHeader @@ -961,23 +1001,17 @@ int WorldSocket::HandlePing (WorldPacket& recvPacket) 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 ()) diff --git a/src/shared/Auth/AuthCrypt.cpp b/src/shared/Auth/AuthCrypt.cpp index c6aae7026..27dce1d6d 100644 --- a/src/shared/Auth/AuthCrypt.cpp +++ b/src/shared/Auth/AuthCrypt.cpp @@ -48,9 +48,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; diff --git a/src/shared/Auth/AuthCrypt.h b/src/shared/Auth/AuthCrypt.h index 60f91b052..a14e4d900 100644 --- a/src/shared/Auth/AuthCrypt.h +++ b/src/shared/Auth/AuthCrypt.h @@ -30,7 +30,6 @@ class AuthCrypt AuthCrypt(); ~AuthCrypt(); - const static size_t CRYPTED_SEND_LEN = 4; const static size_t CRYPTED_RECV_LEN = 6; void Init(); From fa13127cf8a0fff8f664321e69133ad30f594091 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Tue, 2 Dec 2008 22:21:41 +0300 Subject: [PATCH 133/256] Rune cooldowns should work now :) --- src/game/Player.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 889a55b48..e5c818b81 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -565,9 +565,11 @@ bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, SetUInt32Value(UNIT_FIELD_BYTES_0, ( RaceClassGender | ( powertype << 24 ) ) ); //SetUInt32Value(UNIT_FIELD_BYTES_1, unitfield); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP ); - 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 SetUInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); From a2503162fc4e357f8a4c522be6e05f392b5cf3c0 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Wed, 3 Dec 2008 00:27:33 +0300 Subject: [PATCH 134/256] Fixed possible crash --- src/game/Player.cpp | 2 +- src/game/Spell.cpp | 28 +++++++++------------------- src/game/SpellAuras.cpp | 4 ++-- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e5c818b81..bcbe7f93e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17987,7 +17987,7 @@ void Player::SendAurasForTarget(Unit *target) // level data << uint8(aura->GetAuraLevel()); // charges - data << uint8(aura->m_procCharges); + data << uint8(aura->m_procCharges >= 0 ? aura->m_procCharges : 0 ); if(!(auraFlags & AFLAG_NOT_CASTER)) { diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index a0b48bb8a..1727ca15e 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2659,16 +2659,16 @@ void Spell::SendSpellStart() data.append(m_caster->GetPackGUID()); data << uint8(m_cast_count); // pending spell cast? - data << uint32(m_spellInfo->Id); - data << uint32(castFlags); - data << uint32(m_timer); + data << uint32(m_spellInfo->Id); // spellId + data << uint32(castFlags); // cast flags + data << uint32(m_timer); // delay? m_targets.write(&data); if ( castFlags & CAST_FLAG_UNKNOWN6 ) // predicted power? data << uint32(0); - if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns + if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list { uint8 v1 = 0;//m_runesState; uint8 v2 = 0;//((Player*)m_caster)->GetRunesState(); @@ -2678,19 +2678,14 @@ void Spell::SendSpellStart() { 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); - data.hexlike(); m_caster->SendMessageToSet(&data, true); } @@ -2708,11 +2703,11 @@ void Spell::SendSpellGo() if(IsRangedSpell()) castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual - if(m_spellInfo->runeCostID) + 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 + castFlags |= CAST_FLAG_UNKNOWN7; // rune cooldowns list } WorldPacket data(SMSG_SPELL_GO, 50); // guess size @@ -2723,8 +2718,8 @@ void Spell::SendSpellGo() data.append(m_caster->GetPackGUID()); data << uint8(m_cast_count); // pending spell cast? - data << uint32(m_spellInfo->Id); - data << uint32(castFlags); + data << uint32(m_spellInfo->Id); // spellId + data << uint32(castFlags); // cast flags data << uint32(getMSTime()); // timestamp WriteSpellGoTargets(&data); @@ -2734,7 +2729,7 @@ void Spell::SendSpellGo() if ( castFlags & CAST_FLAG_UNKNOWN6 ) // unknown wotlk, predicted power? data << uint32(0); - if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns? + if ( castFlags & CAST_FLAG_UNKNOWN7 ) // rune cooldowns list { uint8 v1 = m_runesState; uint8 v2 = ((Player*)m_caster)->GetRunesState(); @@ -2744,12 +2739,8 @@ void Spell::SendSpellGo() { uint8 m = (1 << i); if(m & v1) // usable before... - { if(!(m & v2)) // ...but on cooldown now... - { data << uint8(0); // some unknown byte (time?) - } - } } } @@ -2773,7 +2764,6 @@ void Spell::SendSpellGo() data << uint8(0); } - data.hexlike(); m_caster->SendMessageToSet(&data, true); } diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index adc1690c0..f427fb422 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -423,7 +423,7 @@ m_periodicTimer(0), m_PeriodicEventId(0), m_AuraDRGroup(DIMINISHING_NONE) modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges); } else - m_procCharges = 0; + m_procCharges = -1; m_isRemovedOnShapeLost = (m_caster_guid==m_target->GetGUID() && m_spellProto->Stances && !(m_spellProto->AttributesEx2 & 0x80000) && !(m_spellProto->Attributes & 0x10000)); @@ -1124,7 +1124,7 @@ void Aura::SendAuraUpdate(bool remove) uint8 auraFlags = GetAuraFlags(); data << uint8(auraFlags); data << uint8(GetAuraLevel()); - data << uint8(GetAuraCharges()); + data << uint8(m_procCharges >= 0 ? m_procCharges : 0); if(!(auraFlags & AFLAG_NOT_CASTER)) { From e58df484a2dcba671a1aa7c1bc5588172480932d Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 4 Dec 2008 05:53:02 +0300 Subject: [PATCH 135/256] Implement aura use in new version of racial trait 20550. Add unit stat mods for rune/runic powers. Last change will also prevent corruption armor and holy resistence values. --- src/game/SpellAuras.cpp | 20 ++++++++++++++------ src/game/SpellAuras.h | 1 + src/game/StatSystem.cpp | 1 + src/game/Unit.cpp | 23 +++++++++++------------ src/game/Unit.h | 6 ++++-- 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index f427fb422..1c7403246 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -332,7 +332,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNULL, //279 &Aura::HandleNULL, //280 ignore armor? &Aura::HandleNULL, //281 increase honor gain? - &Aura::HandleNULL, //282 + &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT &Aura::HandleNULL //283 SPD/heal from AP? }; @@ -4718,24 +4718,32 @@ void Aura::HandleAuraModIncreaseEnergy(bool apply, bool Real) if(int32(powerType) != m_modifier.m_miscvalue) return; - m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_VALUE, float(m_modifier.m_amount), apply); + UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType); + + m_target->HandleStatModifier(unitMod, TOTAL_VALUE, float(m_modifier.m_amount), apply); } -void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool Real) +void Aura::HandleAuraModIncreaseEnergyPercent(bool apply, bool /*Real*/) { Powers powerType = m_target->getPowerType(); if(int32(powerType) != m_modifier.m_miscvalue) return; - m_target->HandleStatModifier(UnitMods(UNIT_MOD_POWER_START + powerType), TOTAL_PCT, float(m_modifier.m_amount), apply); + UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + powerType); + + m_target->HandleStatModifier(unitMod, TOTAL_PCT, float(m_modifier.m_amount), apply); } -void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool Real) +void Aura::HandleAuraModIncreaseHealthPercent(bool apply, bool /*Real*/) { - //m_target->ApplyMaxHealthPercentMod(m_modifier.m_amount,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); +} + /********************************/ /*** FIGHT ***/ /********************************/ diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 6df6e7a10..0a3fbd3d9 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -209,6 +209,7 @@ class MANGOS_DLL_SPEC Aura void HandleManaShield(bool apply, bool Real); void HandleArenaPreparation(bool apply, bool Real); void HandleAuraConvertRune(bool apply, bool Real); + void HandleAuraIncreaseBaseHealthPercent(bool Apply, bool Real); virtual ~Aura(); diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index 828c7fbe0..f7aadca8b 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -849,6 +849,7 @@ void Pet::UpdateMaxHealth() void Pet::UpdateMaxPower(Powers power) { UnitMods unitMod = UnitMods(UNIT_MOD_POWER_START + power); + float addValue = (power == POWER_MANA) ? GetStat(STAT_INTELLECT) - GetCreateStat(STAT_INTELLECT) : 0.0f; float value = GetModifierValue(unitMod, BASE_VALUE) + GetCreatePowers(power); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 95b4cee7c..30cf08c76 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9514,7 +9514,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: @@ -9627,21 +9629,18 @@ 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 diff --git a/src/game/Unit.h b/src/game/Unit.h index 63cfd77da..365e50554 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -301,11 +301,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, @@ -325,7 +327,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 From 4c4f80df5a4e3c0b332c3273b284c07f04df421c Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Thu, 4 Dec 2008 13:29:31 +0300 Subject: [PATCH 136/256] Fixed maps extractor. Patch provided by andstan. Not tested. --- contrib/extractor/ad.exe | Bin 159744 -> 160256 bytes contrib/extractor/adt.cpp | 339 ++++++++++++++++---------------------- contrib/extractor/adt.h | 100 ++++++++--- 3 files changed, 224 insertions(+), 215 deletions(-) diff --git a/contrib/extractor/ad.exe b/contrib/extractor/ad.exe index 2ee6e5be85d4c352e9d96eb902139111bdaafacc..5d8e523260e5345d20a816ac0359ab7c353dc5ac 100755 GIT binary patch delta 37385 zcmcegcViar{+xEeNwfTCXhLj&W=|ttVF5GTyim5t5RjpwB%M^TQNZu zd)Qo2YBV8hVHK52rA9Ln=86oXL7YufsbVi}C^qUC_P&UU)r7F~*mFO(I!o=(79MU<)s2NK7d8DOOW0;g-GPK)MyMSeG@S>7FMY9(92vIMw1x!5^xx*o&n9GKjPL@3`x}nN(S!)&cnKr6zZ0W zvK@!1YtHe6DTt~R>O9naKCz=S{*;SOBuK2RCZO~jjYN(y+3S#JAg%$fl8_e~JY9I2 zD*97Sz&^H1XA7v@g1F>QO>WR>nG{52ZR$X!#Bo!RT1p{m-pN7}`&$Rvj{f$FG=hLD z)&<12ZMZ|_DmF&1$PL(=*`p#&SCQWXRK*4CRe3c^$CFMt##F5HcOKCM?DajBrt+$< z&>iw>tR#dJPKA|&O#o#9d%JrzCY@OSwFj|O>@Y?L?Cq1D^y~WfF?0!@J`F<`T6+B# zYLre$wa(@MyRP_&-Wa`mO?J?OJDz(fM!Y=~+P8 za7?dC8cpjvpl8XH?{6OtfhI< zpn`sLwlMqAk|UVxs*=AbqxdZ}q8CpC14V9D504;kkAq2@JUYhZj}}#V^XKKyDLI^g zk*hm)<8P*P(Rr@Mc`+{Al53@zBTiP4R$-VzG_;})Nf1&+vL0I_`BPZ0VJefto8q6O znc5j5_^R6t%~M)qA6QAX%)-~PgStl0S>mb($LN~*^X5oDA@KG(eCb|WiMH^JV+Y&}Ov z&nrl^l{7j5`!@MdZ32Hn8{rt?X|SZeV`u`(9)RFrp2c|62$5z?p`w6?W>S6-u>tG_ zQw!M)@iVk_N2lul38eniR}`C2tjQ9`QQX=87g6p!93{T-L6zu&2`Xr+hqrR(*RQ`B z+WxfvWW3MJH6~1^How7BRJr+DHcOv~>nUhtz19l~-?{;HAh)SmfG##VqQzMho+>r&LH=UQ zAsgsSKpJ$Z7P~kx|BQDOI(w?-+q0*RqEz3s!w5;C4(U#%8g-|YW$$0jZHK)d(4OhH z9ert0pJ_so{&dhDq`HbIK}8rZ(<$!=AaxKva4

y*9vk$xERciWSs}sUS>Q45Mct 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 JxRSTA{{mG;aTEXm delta 37191 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 !=0) // åñëè äàííûå â Data1 î âîäå åñòü, òî èõ íàäî êîíâåðòèðîâàòü + { + mf.seek(base_pos + LiqOffsData->offsData1);// ïåðåõîäèì ïî ñìåùåíèþ èç offsData1 ÎÒ ÍÀ×ÀËÀ êóñêà + mf.read(LiqChunkData1,24); // ñ÷èòûâàåì ñàìè äàííûå â ñòðóêòóðó òèïà MH2O_Data1 + // çàíîñèì äàííûå ôëàãà äëÿ êóñêà + if(LiqChunkData1->flags & 4 || LiqChunkData1->flags & 8) + MapLiqFlag[chunk_num] |=1; + if(LiqChunkData1->flags & 16) + MapLiqFlag[chunk_num] |=2; + // ïðåäâàðèòåëüíî çàïîëíÿåì âåñü êóñîê äàííûìè - íåò âîäû + for(int j=0;j<81;j++) + { + ChunkLiqHeght[j] = -999999; // no liquid/water + } + // òåïåðü âû÷èñëÿåì òå ÷òî ñ âîäîé è ïåðåçàïèñûâàåì èõ â êóñêå + for(int b=0; b <= LiqChunkData1->height; b++) + { + for(int c=LiqChunkData1->xOffset; c <= (LiqChunkData1->xOffset+LiqChunkData1->width); c++) + { + int n = (9*(LiqChunkData1->yOffset + b))+c; + ChunkLiqHeght[n] = LiqChunkData1->heightLevel1; + } + } + mf.seek(header_pos); // è íå çàáûòü âåðíóòüñÿ íà èñõîäíóþ ïîçèöèþ èìåííî  ÕÈÄÅÐÅ + } + else // åñëè äàííûõ â Data1 íåò, òî íàäî çàïîëíèòü âåñü êóñîê, íî äàííûìè - íåò âîäû + { + for(int j=0; j<81; j++) + ChunkLiqHeght[j] = -999999; // no liquid/water + } + if(!(chunk_num%16)) + m = 1024*(chunk_num/16); // ñìåùåíèå ïî ðÿäàì êóñêîâ ñ ïåðåêðûòèåì = 1024 + k = m +(chunk_num%16)*8; // óñòàíàâëèâàåìñÿ íà íà÷àëüíûé èíäåêñ äëÿ çàïîëíåíèÿ ðÿäà + // çàíîñèì äàííûå êóñêà â ìàññèâ äëÿ êàðòû, ñ ïåðåêðûòèåì è îáðåçàíèåì êóñêîâ òê äàííûõ 81 + // ýòî àíàëîã ñòàðîãî îáðåçàíèÿ ãðàíè÷íûõ ïðàâûõ-áîêîâûõ è íèæíèõ äàííûõ + for(int p=0;p<72;p+=9) // íèæíèå 8 íå çàíîñèì òê îíè äóáëèðóåòñÿ ñëåä êóñêîì + { + for(int s=0; s<8; s++) // 9 çíà÷åíèå â ñòðîêå íå çàíîñèì òê îíî äóáëèðóåòñÿ ñëåä êóñêîì, à â ïðàâûõ-áîêîâûõ îáðåçàåòñÿ äëÿ 128õ128 + { + MapLiqHeight[k] = ChunkLiqHeght[p+s];// :) + k++; + } + k=k+120; + } + } + delete LiqOffsData; + delete LiqChunkData1; + delete []ChunkLiqHeght; + + } + //case 0x4d434e4b: // MCNK + //case 0x4d46424f: // MFBO new in BC + //case 0x4d545846: // MTXF new in WotLK mf.seek(nextpos); } //printf("Loading chunks info\n"); // read individual map chunks for (int j=0; j<16; j++) + { for (int i=0; i<16; i++) { mf.seek((int)mcnk_offsets[j*16+i]); LoadMapChunk(mf,&(mcells->ch[i][j])); + chunk_num++; } - - /* - for(uint32 t=0;t3) testi = 3; if(testj>3) testj = 3; - return (holes & holetab_h[testi] & holetab_v[testj])!=0; + return (holes & holetab_h[testi] & holetab_v[testj])!=0; } inline @@ -207,9 +181,8 @@ void LoadMapChunk(MPQFile & mf, chunk*_chunk) mf.read(&size, 4); size_t lastpos = mf.getPos() + size; - mf.read(&header, 0x80); + mf.read(&header, 0x80); // what if header size got changed? _chunk->area_id =header.areaid ; - _chunk->flag =0; float xbase = header.xpos; float ybase = header.ypos; @@ -222,13 +195,11 @@ void LoadMapChunk(MPQFile & mf, chunk*_chunk) float zmin=999999999.0f; float zmax=-999999999.0f; //must be there, bl!zz uses some crazy format - int nTextures; + //int nTextures; while (mf.getPos() < lastpos) { mf.read(&fourcc,4); mf.read(&size, 4); - //if(size!=580) - // printf("\n sz=%d",size); size_t nextpos = mf.getPos() + size; if(fourcc==0x4d435654) // MCVT { @@ -258,9 +229,9 @@ void LoadMapChunk(MPQFile & mf, chunk*_chunk) } else if(fourcc==0x4d434e52) // MCNR { - nextpos = mf.getPos() + 0x1C0; // size fix + nextpos = mf.getPos() + 0x1C0; // size fix } - else if(fourcc==0x4d434c51) // MCLQ + else if(fourcc==0x4d434c51 && !MH2O_presence) // íå áóäåì ó÷èòûâàòü åñëè óæå áûëè äàííûå â MH2O, ïåðåñòðàõîâêà :) // MCLQ { // liquid / water level //bool haswater; @@ -268,47 +239,51 @@ void LoadMapChunk(MPQFile & mf, chunk*_chunk) mf.read(fcc1,4); flipcc(fcc1); fcc1[4]=0; + ChunkLiqHeght = new float[81]; if (!strcmp(fcc1,"MCSE")) { - for(int i=0;i<9;i++) - for(int j=0;j<9;j++) - _chunk->waterlevel[i][j]=-999999; // no liquid/water + for(int j=0;j<81;j++) + { + ChunkLiqHeght[j] = -999999; // no liquid/water + } } else { float maxheight; mf.read(&maxheight, 4); - - for(int j=0;j<9;j++) - for(int i=0;i<9;i++) - { - mf.read(&h, 4); - mf.read(&h, 4); - if(h > maxheight) - _chunk->waterlevel[i][j]=-999999; - else - _chunk->waterlevel[i][j]=h; - } + for(int j=0;j<81;j++) + { + mf.read(&h, 4); + mf.read(&h, 4); + if(h > maxheight) + ChunkLiqHeght[j] = -999999; + else + ChunkLiqHeght[j] = h; + } if(chunkflags & 4 || chunkflags & 8) - _chunk->flag |=1; + MapLiqFlag[chunk_num] |= 1; if(chunkflags & 16) - _chunk->flag |=2; + MapLiqFlag[chunk_num] |= 2; } + // çàïîëíåì òàê æå êàê â MH2O + if(!(chunk_num%16)) + m = 1024*(chunk_num/16); + k = m +(chunk_num%16)*8; + + for(int p=0;p<72;p+=9) + { + for(int s=0; s<8; s++) + { + MapLiqHeight[k] = ChunkLiqHeght[p+s]; // :) + k++; + } + k=k+120; + } + delete []ChunkLiqHeght; break; } - else if (fourcc==0x4d434c59) // MCLY - { - // texture info - nTextures = (int)size; - } - else if (fourcc==0x4d43414c) // MCAL - { - if (nTextures<=0) - continue; - } - mf.seek(nextpos); } } @@ -330,10 +305,6 @@ double GetZ(double x,double z) { vec v[3]; vec p; - - //bool inWMO=false; - - //if(!inWMO) { //find out quadrant int xc=(int)(x/UNITSIZE); @@ -380,19 +351,6 @@ double GetZ(double x,double z) } } -inline -void TransformWaterData() -{ - cell= new Cell; - - for(int x=0;x<128;x++) - for(int y=0;y<128;y++) - cell->v9[x][y] = mcells->ch[x/8][y/8].waterlevel[x%8][y%8]; - - //and the last 1 - cell->v9[128][128] = mcells->ch[15][15].waterlevel[8][8]; -} - inline void TransformData() { @@ -423,14 +381,24 @@ const char MAP_MAGIC[] = "MAP_2.01"; bool ConvertADT(char * filename,char * filename2) { - //if(!strstr(filename,"oth_32_48"))return false; + MapLiqHeight = new float[16384]; + MapLiqFlag = new char[256]; + for(int j=0; j<256; j++) + MapLiqFlag[j] = 0; + if(!LoadADT(filename)) + { + delete [] MapLiqHeight; + delete [] MapLiqFlag; return false; + } FILE *output=fopen(filename2,"wb"); if(!output) { printf("Can't create the output file '%s'\n",filename2); + delete [] MapLiqHeight; + delete [] MapLiqFlag; return false; } @@ -441,7 +409,7 @@ bool ConvertADT(char * filename,char * filename2) { for(unsigned int y=0;y<16;y++) { - if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id < 0x121F) + if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id < 0x102D) { if(areas[mcells->ch[y][x].area_id]==0xffff) printf("\nCan't find area flag for areaid %u.\n",mcells->ch[y][x].area_id); @@ -456,17 +424,12 @@ bool ConvertADT(char * filename,char * filename2) } } - for(unsigned int x=0;x<16;x++) - for(unsigned int y=0;y<16;y++) - fwrite(&mcells->ch[y][x].flag,1,1,output); - - TransformWaterData(); - - for(unsigned int x=0;x<128;x++) - for(unsigned int y=0;y<128;y++) - fwrite(&cell->v9[y][x],1,sizeof(float),output); - - delete cell; + fwrite(MapLiqFlag,1,256,output); //!!!!!!!! + delete [] MapLiqFlag; + + fwrite(MapLiqHeight,sizeof(float),16384,output); //!!!!!!!! + delete [] MapLiqHeight; + TransformData(); for(unsigned int x=0;x::iterator it = wmos.begin(); it != wmos.end(); ++it) - wmomanager.delbyname(*it); - - wmos.clear(); - wmois.clear(); - - for (std::vector::iterator it = wmomodel.begin(); it != wmomodel.end(); ++it) - { - it->tr.clear(); - - } - //printf("\n %d \n",in); - wmomodel.clear(); - //polygons.clear();*/ + return true; } diff --git a/contrib/extractor/adt.h b/contrib/extractor/adt.h index bae687f6b..4514b6a58 100644 --- a/contrib/extractor/adt.h +++ b/contrib/extractor/adt.h @@ -10,34 +10,31 @@ typedef unsigned short uint16; typedef unsigned int uint32; class Liquid; typedef struct { -float x; -float y; -float z; -}svec; + float x; + float y; + float z; +} svec; typedef struct { -double x; -double y; -double z; -}vec; + double x; + double y; + double z; +} vec; typedef struct{ vec v[3]; -}triangle; +} triangle; typedef struct{ -float v9[16*8+1][16*8+1]; -float v8[16*8][16*8]; -}Cell; + float v9[16*8+1][16*8+1]; + float v8[16*8][16*8]; +} Cell; typedef struct{ double v9[9][9]; double v8[8][8]; -uint16 area_id; -//Liquid *lq; -float waterlevel[9][9]; -uint8 flag; -}chunk; + uint16 area_id; +} chunk; class WMO; class WMOManager; @@ -45,9 +42,72 @@ void fixname(std::string &name); typedef struct { -chunk ch[16][16]; -}mcell; + chunk ch[16][16]; +} mcell; + +struct MapChunkHeader { + uint32 flags; + uint32 ix; + uint32 iy; + uint32 nLayers; + uint32 nDoodadRefs; + uint32 ofsHeight; + uint32 ofsNormal; + uint32 ofsLayer; + uint32 ofsRefs; + uint32 ofsAlpha; + uint32 sizeAlpha; + uint32 ofsShadow; + uint32 sizeShadow; + uint32 areaid; + uint32 nMapObjRefs; + uint32 holes; + uint16 s1; + uint16 s2; + uint32 d1; + uint32 d2; + uint32 d3; + uint32 predTex; + uint32 nEffectDoodad; + uint32 ofsSndEmitters; + uint32 nSndEmitters; + uint32 ofsLiquid; // not use in WotLK + uint32 sizeLiquid; // not use in WotLK + float zpos; + float xpos; + float ypos; + uint32 textureId; // new offsColorValues in WotLK + uint32 props; + uint32 effectId; +}; + +typedef struct { + uint32 offsData1; + uint32 used; + uint32 offsData2; +} MH2O_offsData; + +typedef struct { + uint16 flags; + uint16 type; + float heightLevel1; + float heightLevel2; + byte xOffset; + byte yOffset; + byte width; + byte height; + uint32 ofsData2a; + uint32 ofsData2b; +} MH2O_Data1; + class MPQFile; -void LoadMapChunk(MPQFile &,chunk*); + +bool MH2O_presence; +MH2O_offsData *LiqOffsData; +MH2O_Data1 *LiqChunkData1; +float *ChunkLiqHeght, *MapLiqHeight; +char* MapLiqFlag; +uint32 k, m, chunk_num; +void LoadMapChunk(MPQFile &, chunk*); bool LoadWMO(char* filename); #endif From 99db25c9eb1117cb11a4b96168f3d565b01943ac Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Thu, 4 Dec 2008 19:22:50 +0300 Subject: [PATCH 137/256] Replaced hardcoded maxareaid with dbc data in maps extractor. Reduced number of cells (doubled visibility distance). --- contrib/extractor/System.cpp | 3 +++ contrib/extractor/VC71_ad.vcproj | 4 ++-- contrib/extractor/VC80_ad.vcproj | 4 ++-- contrib/extractor/VC90_ad.vcproj | 4 ++-- contrib/extractor/ad.exe | Bin 160256 -> 160256 bytes contrib/extractor/adt.cpp | 6 ++++-- src/game/GridDefines.h | 4 ++-- 7 files changed, 15 insertions(+), 10 deletions(-) diff --git a/contrib/extractor/System.cpp b/contrib/extractor/System.cpp index d86af0b14..30e28e211 100644 --- a/contrib/extractor/System.cpp +++ b/contrib/extractor/System.cpp @@ -31,6 +31,7 @@ map_id * map_ids; uint16 * areas; char output_path[128]="."; char input_path[128]="."; +uint32 maxAreaId = 0; enum Extract { @@ -146,6 +147,8 @@ void ReadAreaTableDBC() for(unsigned int x=0; xN!~zL6kJj4 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 delta 8771 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 DT0+n+ diff --git a/contrib/extractor/adt.cpp b/contrib/extractor/adt.cpp index a42141210..af5a671c6 100644 --- a/contrib/extractor/adt.cpp +++ b/contrib/extractor/adt.cpp @@ -17,7 +17,9 @@ //#include unsigned int iRes=256; -extern uint16*areas; +extern uint16 *areas; + +extern uint32 maxAreaId; vec wmoc; @@ -409,7 +411,7 @@ bool ConvertADT(char * filename,char * filename2) { for(unsigned int y=0;y<16;y++) { - if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id < 0x102D) + if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id <= maxAreaId) { if(areas[mcells->ch[y][x].area_id]==0xffff) printf("\nCan't find area flag for areaid %u.\n",mcells->ch[y][x].area_id); diff --git a/src/game/GridDefines.h b/src/game/GridDefines.h index 0942c5c31..ced42871b 100644 --- a/src/game/GridDefines.h +++ b/src/game/GridDefines.h @@ -41,10 +41,10 @@ class Player; #define MIN_GRID_DELAY MINUTE*1000 #define MIN_MAP_UPDATE_DELAY 50 -#define MAX_NUMBER_OF_CELLS 8 +#define MAX_NUMBER_OF_CELLS 4 #define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS) -#define CENTER_GRID_CELL_ID 256 +#define CENTER_GRID_CELL_ID 128 #define CENTER_GRID_CELL_OFFSET (SIZE_OF_GRID_CELL/2) #define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS) From a69bc59f1dd426fab9a1a8026a5041c82089e1e1 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Thu, 4 Dec 2008 22:56:06 +0300 Subject: [PATCH 138/256] Fixed some typos, updated areaflags enum --- contrib/extractor/ad.exe | Bin 160256 -> 160256 bytes contrib/extractor/adt.cpp | 121 ++++++++++++++++----------------- contrib/extractor/adt.h | 2 +- src/shared/Database/DBCEnums.h | 28 +++++--- 4 files changed, 79 insertions(+), 72 deletions(-) diff --git a/contrib/extractor/ad.exe b/contrib/extractor/ad.exe index ad4c2f80c347a42c96825428a1f4b97a2b12760d..31de435c4e00f7daba8252f79a9703f9896b9ff9 100755 GIT binary patch delta 3819 zcma)-e^iuJ8prQ*nE^%tXAlHK1a(|7Pyq)6QF>oMgTfHq5>zYEipAcS)wA2nhWys_s($g_(we zbMJlTof&(Z$=+tF>KxP=ketnWMl187-eh9z6fw5m>x|VbG>U&WOG~GBsYbs{;hZ9L zZm2B1jeZ#0t+vz(jH~^JuW!!>rZ|U9IdEZoO)CT(H;#uT3+B7zU zv7dq+;~TZzeu>nm|LA9=*t&On@^al9U^)UDQ6tZtw9T{G=nltJYrMQfxceI|$TX`n$w!-DiVNM1B}9g}%B@-cjCEtUh4!*(ocY>T*(G`8w~*+* zpdB*}E_IBTlZMVAB}e|j6vn1p-|aTs>FzFTGL$zi9a1Y-bKRkJa=$lV=ebR=%bNTX z8|VBn-*IvFXO5)-g@?LSHq9Nr4^g+Uwx)aO$Z3U*aJpCQfiF~6nd1Hi2dI@ra@|cZ z%bLuI+LOKdKIGc%nYc2o@$%Dmlvv~cX_iK}R@G|*&Cnn2UC(Kdb|x^6|L2C@D+q5v zqc)(=>mjmDKb$&k47jGU(*yi|GNE(Yr+xBe$IbsncTJWQqF#DNaAz=8=(eHnaN4hZ zH%y~a{n?lnf8V3y6joTJrzac;qAS{sM=$mF&rw)ka2^ZtXf*MrzP)Yla!jox2sbc4bV;O6yWT*F>vXe|BvSC$rw* zIBukJy|Q{qVCk1aVf{BKY!~SFH-#++Z6K>gVF$s$w-r_kj2jh}2*!hmO$vJzm^UkI z9Vp*|i*HrfW7`zA0sQo?!k*r)u)#YN_5>KQQ(-5-S&+O-VOvn+ebBy9;p~pSYIBmj zt#j`qcwXJB=3gz#0x~>s%NvVI81>M00ju8R+PiyXAlx;5jYf@VwNc-%9_@(>Q`1 zCTclcANb(=Rd(C(d_Y;NPweM-6^|nx5i+={4Yogwc&+7dG#%Bh9UhM709S%lE~7v> zc)ar4_rfL%f@|V(tdFK)`YRYuC95e!Nq&G=~jzU-j(Q*6D3dq10RO zSz%;#Y7?7>$;hH+YsPW8^qcLGt2oh@kOr_H>;PN9Tc8S5bZRG?vqEH~qg!rx1>6Dw zU0UMdxv7h<{o0^tn7`4Wk}l7IWpGtF>>c2!R(vsJ^I4-6hAtvZ|}HHl&aTU9TCEPE;+yOp@~5>S6G5+ z4b2cDn66QX^VPmoW1uSM@4`v(rA5wX2GUJaDw_)CfNkJg=ZYA5 z$UxD~^>GwNMCBOvHwl}!YH0Plk>AgWPiA>cFTBMoF8NZUl#Ns6Oo&ZQ^mpn(>P zxbLay;2A2Q5z&|MkJU3?{~13Z0V*pStg;=7$~M{Wt|cB&nax@G1AR|Md%VJ&&V^@b zJGT_9R9Hd2!VaaUGmq^YdY&FL7`=9JJAD(Eu=xXprS&i?Bb_y!KtA~WqGuNsy|^fP z-m<6XEiRc~vwL4tI}Rsw^mfZaO^$E#Yn6kZ7nZ94*w*I8d%wIGRr$zP4wzx<@zkXf0G0*$I_d zt>U80G7F0h*O(?I*!U2*C$#AzF!Y}vBr-o6|WDM`pZ zDrP6~R0frpspdw~NC`JP|wGPU543gV)_#!~d@$Z47@3JJ*ikVWwrs zmWSLgJ{jZbb;lT;GWL-8a4e4qDvG@8S`jH$rtp47 zTa?O@1*P%`V>!$UF(?(ut%JN<%j7*`5>}~9%*P7VinS14q=*Hnd>}uY;Zdp)ml5Q9 zb*9R$&-A+biQ(gTRG%}m@0JRmt%@Raf@X;7kcIbZ06{uYd&*HI@?i+^isn_wdkCgkyirOrmasQp2#%x|=c%ZGZ z>w|6W?3jd~tL*z85!ZRJtK?1RPdv~O3;z3n-Em%?&ZiraQtx;_5P3B@N*(I`aW0+3 H9ijgRp9#ZK delta 3750 zcma);3shBA8prpyxfi%1a4&*@JOsTa#zR0bUN+|-6^yt~lDmn)9Zb^QMNL=qjF;#|Fk(=0QGWVyuf8`;*%lrden#|H~jPn|6^+zeFLNd~|NG z5KYnojpON@Hpw_LV9Py>CAVG*Ffdli8Vt-Csnr;*)T-??##r9YVXVwhUucb)R-bPT zcW%|r7!!tX(a*$NuS}2k(Zj%%-Zjt=;FB4gWRTv>>_^hWKRXC}32kzNJ3F7O&>x)UMa z1=uFEX}i6WsZBrQWu(}(y9V+KoU38leA`fCs&mv%SF>@KZH3lEc@rVdk2OD2^w7B)7Z{iOyr% zQPYUbY0jbl>hG^>Gc0diG;*6)Z!t+q#QBvn?82y1!Rt z)1AXKb#id&_VrRzL`eV&QjRp-~sR(Fa`_(H)bmABIpGB^c$0>b7T}2 z_!D_+B~z<;-#NW|YKFDRR4=1)eRNH@kzUnvR*W{7 z&+b;(>ZLL1ORbB%9QRt8{_N^}PE0>&J8q;(eRJbN-|BrrVW#y8+W zwhQ=eQdlGS0gTwJuz29JMPbhXwpC%(pt1=!zC&Sm?LnI->k5JR~42CB3@Hi zJ2(PjURPKHYU~6jHY=Qcr#Eg*m3QlS^DbQb-&ALxGO27wL1i{`7z=UzjH$3@!dmRI z=D>Q#Wfj8;g|(vuhQnBjYawzS#wTEOs=My})T(Pc`>ij_)%rXZrggRl8_y!OOY3gW8zSAdepx#U z7?8Cl(Ky`xPo{pw-JRqSY=R&hSqvj&r@9_>PV zZlLtr`epf3zzKft(XtPeWENlj?{S!6{>pKb^t!eugBvPguLG@GZFdwezN&dRVx+`7 z60I@-B?2MgzzX6(3djOEV1^cbA#aGgZ8_#uU=`S;FS(HJMMre|p?j2q~WQpnY*9{bY)m7pJnaJ5{y;^nsjM zl}!OJgU{@?7#e0Evwc?_1ryorAH~xZ6*b;kK)nXaw>MSN3xg>}#Me>@C5o47sg4ru zLzmIfu{6kjsfCg}<4=94vc!*6wi3J#{td=|tg_#NouC2ux2ntlbo+gK$s9?47Bf#! z9IdjiI6?0js90ouh3{_zncq7_#T0M8h##AQvFz{oKnzyd!VxN4r>N}3nwx7Q-c^~^ zUVoatB4c@?!kX<*eof8XQm|BE1+x{lKO4Up(zcH}NB0?wZoA?F9f?a?^MS$=2ADH3 zo9+1=`QU;1kI!GQcz)C)RS!Q>UO8{UeC(qf>)oPa2;b^^*iU79G5rEtYPLt^pb;-#G@XT@T33XipP%u$elk(cdCX%Ht< z_!LXSieH|~`yxFRxvioom1mMstWV`(0X^OBP0Dn67=7L1Kq^m0hwG_)TmWD5%Nl+4 z;_mVMA#~n0o(G#sFSs|^Bt9AMI_t~h`9wM{lJ4Te>3uO(%3M()C0jH~SteSfToIj8 z>P4@V)54MlSuc{LoEB51ydf&2j1i4eE{PT?7e%L(1knrexbaU#*fM#j&*>Wq>jfBM zcm@yh`P@fky+AsqAj0=iyy0@hK$FFibRIm^-(O`RKyfX&FF*Q=*VFl1gNOOe zjkxK0JVGo@=R=Lw;VO#}l*z-4l`yMBbS9EJqTQ`!@+L7EtF%ze!wNNu)et^c5oMV? zk{_AqQnHCl2=e@Tmdd`J<#u_BFdDQ`Jw`AlqMRbREriVUx>~u zY$NPBm5mj>(z8TZCcxucgO8C&ngCCvm@4HXQ6XidXq57zXpxdFI;GUP#H)Yz&0{h? zdqQQxo^&_=!W7LWD2(I2I-mqCxLaX0&?d|kXt@}Z%VQ_sG7RB`*Hni8*x4;(#kO2N z@z$N~#yq~!a9gcq*V}4szdRYAtGruo5w~+&^~BT}e9~=gvG~W^JRSR`8GMEzHTGZb U2O@7xjs-UL*4P)#;kKav0KzStu>b%7 diff --git a/contrib/extractor/adt.cpp b/contrib/extractor/adt.cpp index af5a671c6..b7f54f8ad 100644 --- a/contrib/extractor/adt.cpp +++ b/contrib/extractor/adt.cpp @@ -15,7 +15,6 @@ #include "adt.h" #include "mpq_libmpq.h" -//#include unsigned int iRes=256; extern uint16 *areas; @@ -64,7 +63,7 @@ bool LoadADT(char* filename) //if(fourcc==0x4d564552) // MVER if(fourcc==0x4d43494e) // MCIN { - for (int i=0; i<256; i++) + for (int i=0; i<256; ++i) { mf.read(&mcnk_offsets[i],4); mf.read(&mcnk_sizes[i],4); @@ -86,40 +85,41 @@ bool LoadADT(char* filename) uint32 header_pos = 0; LiqOffsData = new MH2O_offsData; LiqChunkData1 = new MH2O_Data1; - ChunkLiqHeght = new float[81]; - for(;chunk_num < 256; chunk_num++) + ChunkLiqHeight = new float[81]; + for(;chunk_num < 256; ++chunk_num) { mf.read(LiqOffsData,12); header_pos = mf.getPos(); if(LiqOffsData->offsData1 !=0) // åñëè äàííûå â Data1 î âîäå åñòü, òî èõ íàäî êîíâåðòèðîâàòü { - mf.seek(base_pos + LiqOffsData->offsData1);// ïåðåõîäèì ïî ñìåùåíèþ èç offsData1 ÎÒ ÍÀ×ÀËÀ êóñêà + // ïåðåõîäèì ïî ñìåùåíèþ èç offsData1 ÎÒ ÍÀ×ÀËÀ êóñêà + mf.seek(base_pos + LiqOffsData->offsData1); mf.read(LiqChunkData1,24); // ñ÷èòûâàåì ñàìè äàííûå â ñòðóêòóðó òèïà MH2O_Data1 // çàíîñèì äàííûå ôëàãà äëÿ êóñêà if(LiqChunkData1->flags & 4 || LiqChunkData1->flags & 8) - MapLiqFlag[chunk_num] |=1; + MapLiqFlag[chunk_num] |= 1; if(LiqChunkData1->flags & 16) - MapLiqFlag[chunk_num] |=2; + MapLiqFlag[chunk_num] |= 2; // ïðåäâàðèòåëüíî çàïîëíÿåì âåñü êóñîê äàííûìè - íåò âîäû - for(int j=0;j<81;j++) + for(int j=0;j<81;++j) { - ChunkLiqHeght[j] = -999999; // no liquid/water + ChunkLiqHeight[j] = -999999; // no liquid/water } // òåïåðü âû÷èñëÿåì òå ÷òî ñ âîäîé è ïåðåçàïèñûâàåì èõ â êóñêå - for(int b=0; b <= LiqChunkData1->height; b++) + for(int b=0; b <= LiqChunkData1->height; ++b) { - for(int c=LiqChunkData1->xOffset; c <= (LiqChunkData1->xOffset+LiqChunkData1->width); c++) + for(int c=LiqChunkData1->xOffset; c <= (LiqChunkData1->xOffset+LiqChunkData1->width); ++c) { int n = (9*(LiqChunkData1->yOffset + b))+c; - ChunkLiqHeght[n] = LiqChunkData1->heightLevel1; + ChunkLiqHeight[n] = LiqChunkData1->heightLevel1; } } mf.seek(header_pos); // è íå çàáûòü âåðíóòüñÿ íà èñõîäíóþ ïîçèöèþ èìåííî  ÕÈÄÅÐÅ } else // åñëè äàííûõ â Data1 íåò, òî íàäî çàïîëíèòü âåñü êóñîê, íî äàííûìè - íåò âîäû { - for(int j=0; j<81; j++) - ChunkLiqHeght[j] = -999999; // no liquid/water + for(int j=0; j<81; ++j) + ChunkLiqHeight[j] = -999999; // no liquid/water } if(!(chunk_num%16)) m = 1024*(chunk_num/16); // ñìåùåíèå ïî ðÿäàì êóñêîâ ñ ïåðåêðûòèåì = 1024 @@ -128,17 +128,17 @@ bool LoadADT(char* filename) // ýòî àíàëîã ñòàðîãî îáðåçàíèÿ ãðàíè÷íûõ ïðàâûõ-áîêîâûõ è íèæíèõ äàííûõ for(int p=0;p<72;p+=9) // íèæíèå 8 íå çàíîñèì òê îíè äóáëèðóåòñÿ ñëåä êóñêîì { - for(int s=0; s<8; s++) // 9 çíà÷åíèå â ñòðîêå íå çàíîñèì òê îíî äóáëèðóåòñÿ ñëåä êóñêîì, à â ïðàâûõ-áîêîâûõ îáðåçàåòñÿ äëÿ 128õ128 + for(int s=0; s<8; ++s) // 9 çíà÷åíèå â ñòðîêå íå çàíîñèì òê îíî äóáëèðóåòñÿ ñëåä êóñêîì, à â ïðàâûõ-áîêîâûõ îáðåçàåòñÿ äëÿ 128õ128 { - MapLiqHeight[k] = ChunkLiqHeght[p+s];// :) - k++; + MapLiqHeight[k] = ChunkLiqHeight[p+s]; + ++k; } k=k+120; } } delete LiqOffsData; delete LiqChunkData1; - delete []ChunkLiqHeght; + delete []ChunkLiqHeight; } //case 0x4d434e4b: // MCNK @@ -149,13 +149,13 @@ bool LoadADT(char* filename) //printf("Loading chunks info\n"); // read individual map chunks - for (int j=0; j<16; j++) + for (int j=0; j<16; ++j) { - for (int i=0; i<16; i++) + for (int i=0; i<16; ++i) { mf.seek((int)mcnk_offsets[j*16+i]); LoadMapChunk(mf,&(mcells->ch[i][j])); - chunk_num++; + ++chunk_num; } } mf.close(); @@ -171,8 +171,7 @@ bool isHole(int holes, int i, int j) return (holes & holetab_h[testi] & holetab_v[testj])!=0; } -inline -void LoadMapChunk(MPQFile & mf, chunk*_chunk) +inline void LoadMapChunk(MPQFile & mf, chunk*_chunk) { float h; uint32 fourcc; @@ -196,8 +195,7 @@ void LoadMapChunk(MPQFile & mf, chunk*_chunk) int chunkflags = header.flags; float zmin=999999999.0f; float zmax=-999999999.0f; - //must be there, bl!zz uses some crazy format - //int nTextures; + // must be there, bl!zz uses some crazy format while (mf.getPos() < lastpos) { mf.read(&fourcc,4); @@ -205,8 +203,8 @@ void LoadMapChunk(MPQFile & mf, chunk*_chunk) size_t nextpos = mf.getPos() + size; if(fourcc==0x4d435654) // MCVT { - for (int j=0; j<17; j++) - for (int i=0; i<((j%2)?8:9); i++) + for (int j=0; j<17; ++j) + for (int i=0; i<((j%2)?8:9); ++i) { mf.read(&h,4); float z=h+ybase; @@ -236,32 +234,31 @@ void LoadMapChunk(MPQFile & mf, chunk*_chunk) else if(fourcc==0x4d434c51 && !MH2O_presence) // íå áóäåì ó÷èòûâàòü åñëè óæå áûëè äàííûå â MH2O, ïåðåñòðàõîâêà :) // MCLQ { // liquid / water level - //bool haswater; char fcc1[5]; mf.read(fcc1,4); flipcc(fcc1); fcc1[4]=0; - ChunkLiqHeght = new float[81]; + ChunkLiqHeight = new float[81]; if (!strcmp(fcc1,"MCSE")) { - for(int j=0;j<81;j++) + for(int j=0;j<81;++j) { - ChunkLiqHeght[j] = -999999; // no liquid/water + ChunkLiqHeight[j] = -999999; // no liquid/water } } else { float maxheight; mf.read(&maxheight, 4); - for(int j=0;j<81;j++) + for(int j=0;j<81;++j) { mf.read(&h, 4); mf.read(&h, 4); if(h > maxheight) - ChunkLiqHeght[j] = -999999; + ChunkLiqHeight[j] = -999999; else - ChunkLiqHeght[j] = h; + ChunkLiqHeight[j] = h; } if(chunkflags & 4 || chunkflags & 8) @@ -276,14 +273,14 @@ void LoadMapChunk(MPQFile & mf, chunk*_chunk) for(int p=0;p<72;p+=9) { - for(int s=0; s<8; s++) + for(int s=0; s<8; ++s) { - MapLiqHeight[k] = ChunkLiqHeght[p+s]; // :) - k++; + MapLiqHeight[k] = ChunkLiqHeight[p+s]; + ++k; } k=k+120; } - delete []ChunkLiqHeght; + delete []ChunkLiqHeight; break; } mf.seek(nextpos); @@ -296,19 +293,18 @@ double solve (vec *v,vec *p) double b = v[0].z *(v[1].x - v[2].x) + v[1].z *(v[2].x - v[0].x) + v[2].z *(v[0].x - v[1].x); double c = v[0].x *(v[1].y - v[2].y) + v[1].x *(v[2].y - v[0].y) + v[2].x *(v[0].y - v[1].y); double d = v[0].x *(v[1].y*v[2].z - v[2].y*v[1].z) + v[1].x* (v[2].y*v[0].z - v[0].y*v[2].z) + v[2].x* (v[0].y*v[1].z - v[1].y*v[0].z); - //-d + // -d - //plane equation ax+by+cz+d=0 + // plane equation ax+by+cz+d=0 return ((a*p->x+c*p->z-d)/b); } -inline -double GetZ(double x,double z) +inline double GetZ(double x, double z) { vec v[3]; vec p; { - //find out quadrant + // find out quadrant int xc=(int)(x/UNITSIZE); int zc=(int)(z/UNITSIZE); if(xc>127)xc=127; @@ -353,27 +349,26 @@ double GetZ(double x,double z) } } -inline -void TransformData() +inline void TransformData() { cell= new Cell; - for(int x=0;x<128;x++) + for(int x=0;x<128;++x) { - for(int y=0;y<128;y++) + for(int y=0;y<128;++y) { cell->v8[x][y] = (float)mcells->ch[x/8][y/8].v8[x%8][y%8]; cell->v9[x][y] = (float)mcells->ch[x/8][y/8].v9[x%8][y%8]; } - //extra 1 point on bounds + // extra 1 point on bounds cell->v9[x][128] = (float)mcells->ch[x/8][15].v9[x%8][8]; - //x==y + // x==y cell->v9[128][x] = (float)mcells->ch[15][x/8].v9[8][x%8]; } - //and the last 1 + // and the last 1 cell->v9[128][128] = (float)mcells->ch[15][15].v9[8][8]; delete mcells; @@ -385,8 +380,10 @@ bool ConvertADT(char * filename,char * filename2) { MapLiqHeight = new float[16384]; MapLiqFlag = new char[256]; - for(int j=0; j<256; j++) + for(int j = 0; j < 256; ++j) MapLiqFlag[j] = 0; + for(int j = 0; j < 16384; ++j) + MapLiqHeight[j] = -999999; if(!LoadADT(filename)) { @@ -407,9 +404,9 @@ bool ConvertADT(char * filename,char * filename2) // write magic header fwrite(MAP_MAGIC,1,8,output); - for(unsigned int x=0;x<16;x++) + for(unsigned int x=0;x<16;++x) { - for(unsigned int y=0;y<16;y++) + for(unsigned int y=0;y<16;++y) { if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id <= maxAreaId) { @@ -426,22 +423,24 @@ bool ConvertADT(char * filename,char * filename2) } } - fwrite(MapLiqFlag,1,256,output); //!!!!!!!! + fwrite(MapLiqFlag,1,256,output); delete [] MapLiqFlag; - fwrite(MapLiqHeight,sizeof(float),16384,output); //!!!!!!!! + fwrite(MapLiqHeight,sizeof(float),16384,output); delete [] MapLiqHeight; TransformData(); - for(unsigned int x=0;x Date: Fri, 5 Dec 2008 02:01:05 +0300 Subject: [PATCH 139/256] Use 2D distance for visibility checks --- contrib/extractor/adt.cpp | 2 + src/game/Corpse.cpp | 2 +- src/game/DynamicObject.cpp | 2 +- src/game/GameObject.cpp | 2 +- src/game/Object.cpp | 13 ++++++ src/game/Object.h | 1 + src/game/Unit.cpp | 76 ++++++++++++++++++++++++++------ src/game/Unit.h | 2 +- src/mangosd/mangosd.conf.dist.in | 12 ++--- 9 files changed, 88 insertions(+), 24 deletions(-) diff --git a/contrib/extractor/adt.cpp b/contrib/extractor/adt.cpp index b7f54f8ad..c8cd50e20 100644 --- a/contrib/extractor/adt.cpp +++ b/contrib/extractor/adt.cpp @@ -204,6 +204,7 @@ inline void LoadMapChunk(MPQFile & mf, chunk*_chunk) if(fourcc==0x4d435654) // MCVT { for (int j=0; j<17; ++j) + { for (int i=0; i<((j%2)?8:9); ++i) { mf.read(&h,4); @@ -226,6 +227,7 @@ inline void LoadMapChunk(MPQFile & mf, chunk*_chunk) if(z>zmax)zmax=z; //if(zIsInWorld() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)); + return IsInWorld() && u->IsInWorld() && IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)); } diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp index 21c689e57..31df66e94 100644 --- a/src/game/DynamicObject.cpp +++ b/src/game/DynamicObject.cpp @@ -148,5 +148,5 @@ void DynamicObject::Delay(int32 delaytime) bool DynamicObject::isVisibleForInState(Player const* u, bool inVisibleList) const { - return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)); + return IsInWorld() && u->IsInWorld() && IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f)); } diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 866157571..fb14abb3b 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -738,7 +738,7 @@ bool GameObject::isVisibleForInState(Player const* u, bool inVisibleList) const } // check distance - return IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject() + + return IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f) ); } diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 1c8ad7bed..1ff78e3c0 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1119,6 +1119,19 @@ bool WorldObject::IsWithinDistInMap(const WorldObject* obj, const float dist2com return distsq < maxdist * maxdist; } +bool WorldObject::IsWithinDistInMap2d(const WorldObject* obj, const float dist2compare) const +{ + if (!obj || !IsInMap(obj)) return false; + + float dx = GetPositionX() - obj->GetPositionX(); + float dy = GetPositionY() - obj->GetPositionY(); + float distsq = dx*dx + dy*dy; + float sizefactor = GetObjectSize() + obj->GetObjectSize(); + float maxdist = dist2compare + sizefactor; + + return distsq < maxdist * maxdist; +} + bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const { if (!IsInMap(obj)) return false; diff --git a/src/game/Object.h b/src/game/Object.h index 974e6b0b3..5cb93a7de 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -418,6 +418,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object float GetDistanceZ(const WorldObject* obj) const; bool IsInMap(const WorldObject* obj) const { return GetMapId()==obj->GetMapId() && GetInstanceId()==obj->GetInstanceId(); } bool IsWithinDistInMap(const WorldObject* obj, const float dist2compare) const; + bool IsWithinDistInMap2d(const WorldObject* obj, const float dist2compare) const; bool IsWithinLOS(const float x, const float y, const float z ) const; bool IsWithinLOSInMap(const WorldObject* obj) const; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 30cf08c76..dd67be95f 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -8547,7 +8547,7 @@ int32 Unit::ModifyPower(Powers power, int32 dVal) return gain; } -bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList) const +bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList, bool is2dDistance) const { if(!u) return false; @@ -8598,40 +8598,88 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList) if(u->isInFlight()) // what see player in flight { // use object grey distance for all (only see objects any way) - if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))) - return false; + if(is2dDistance) + { + if (!IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))) + return false; + } + else + { + if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))) + return false; + } } else if(!isAlive()) // distance for show body { - if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))) - return false; + if(is2dDistance) + { + if (!IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))) + return false; + } + else + { + if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))) + return false; + } } else if(GetTypeId()==TYPEID_PLAYER) // distance for show player { if(u->GetTypeId()==TYPEID_PLAYER) { // Players far than max visible distance for player or not in our map are not visible too - if (!at_same_transport && !IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) - return false; + if(is2dDistance) + { + if (!at_same_transport && !IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } + else + { + if (!at_same_transport && !IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } } else { // Units far than max visible distance for creature or not in our map are not visible too - if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) - return false; + if(is2dDistance) + { + if (!IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } + else + { + if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } } } else if(GetCharmerOrOwnerGUID()) // distance for show pet/charmed { // Pet/charmed far than max visible distance for player or not in our map are not visible too - if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) - return false; + if(is2dDistance) + { + if (!IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } + else + { + if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } } else // distance for show creature { // Units far than max visible distance for creature or not in our map are not visible too - if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) - return false; + if(is2dDistance) + { + if (!IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } + else + { + if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) + return false; + } } // Visible units, always are visible for all units, except for units under invisibility @@ -9444,7 +9492,7 @@ Unit* Unit::GetUnit(WorldObject& object, uint64 guid) bool Unit::isVisibleForInState( Player const* u, bool inVisibleList ) const { - return isVisibleForOrDetect(u,false,inVisibleList); + return isVisibleForOrDetect(u, false, inVisibleList, true); } uint32 Unit::GetCreatureType() const diff --git a/src/game/Unit.h b/src/game/Unit.h index 365e50554..3f3191eea 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1139,7 +1139,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void SetVisibility(UnitVisibility x); // common function for visibility checks for player/creatures with detection code - bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false) const; + bool isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList = false, bool is2dDistance = false) const; bool canDetectInvisibilityOf(Unit const* u) const; // virtual functions for all world objects types diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 0bda27130..e2ce71475 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -869,9 +869,9 @@ GM.StartLevel = 1 # Visibility.Distance.Creature # Visibility.Distance.Player # Visibility distance for different in game object -# Max limited by active player zone: ~ 166 +# Max limited by active player zone: ~ 333 # Min limit dependent from objects -# Default: 66 (cell size) +# Default: 132 (cell size) # Min limit is max aggro radius (45) * Rate.Creature.Aggro # # Visibility.Distance.Object @@ -897,10 +897,10 @@ GM.StartLevel = 1 ################################################################################################################### Visibility.GroupMode = 0 -Visibility.Distance.Creature = 66 -Visibility.Distance.Player = 66 -Visibility.Distance.Object = 66 -Visibility.Distance.InFlight = 66 +Visibility.Distance.Creature = 132 +Visibility.Distance.Player = 132 +Visibility.Distance.Object = 132 +Visibility.Distance.InFlight = 132 Visibility.Distance.Grey.Unit = 1 Visibility.Distance.Grey.Object = 10 From b68b0acb296e85a7de2c4f9a5bfdeb696edad5e0 Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 5 Dec 2008 13:08:23 +0100 Subject: [PATCH 140/256] Fixed loosing almost all auras at first melee attack after login by partially reverting ce8bce685e4571cb8060a5c75d706570f98c28ca --- src/game/Player.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index bcbe7f93e..8ec5f1e26 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -14344,7 +14344,7 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff) remaincharges = spellproto->procCharges; } else - remaincharges = 0; + remaincharges = -1; //do not load single target auras (unless they were cast by the player) if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto)) From 588edbcedb2d79a30d64462942f82d6d92f4e65a Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Fri, 5 Dec 2008 18:38:17 +0300 Subject: [PATCH 141/256] Fixed merge --- src/game/GameObject.cpp | 2 +- src/game/Object.cpp | 13 ---------- src/game/Object.h | 1 - src/game/Unit.cpp | 54 +++++------------------------------------ 4 files changed, 7 insertions(+), 63 deletions(-) diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index 6a69e5288..433493492 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -738,7 +738,7 @@ bool GameObject::isVisibleForInState(Player const* u, bool inVisibleList) const } // check distance - return IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForObject() + + return IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false); } diff --git a/src/game/Object.cpp b/src/game/Object.cpp index b02794884..ebd2279b7 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1123,19 +1123,6 @@ bool WorldObject::IsWithinDistInMap(const WorldObject* obj, const float dist2com return distsq < maxdist * maxdist; } -bool WorldObject::IsWithinDistInMap2d(const WorldObject* obj, const float dist2compare) const -{ - if (!obj || !IsInMap(obj)) return false; - - float dx = GetPositionX() - obj->GetPositionX(); - float dy = GetPositionY() - obj->GetPositionY(); - float distsq = dx*dx + dy*dy; - float sizefactor = GetObjectSize() + obj->GetObjectSize(); - float maxdist = dist2compare + sizefactor; - - return distsq < maxdist * maxdist; -} - bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const { if (!IsInMap(obj)) return false; diff --git a/src/game/Object.h b/src/game/Object.h index 8be15b4f7..16e1fbfdf 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -418,7 +418,6 @@ class MANGOS_DLL_SPEC WorldObject : public Object float GetDistanceZ(const WorldObject* obj) const; bool IsInMap(const WorldObject* obj) const { return GetMapId()==obj->GetMapId() && GetInstanceId()==obj->GetInstanceId(); } bool IsWithinDistInMap(const WorldObject* obj, const float dist2compare, const bool is3D = true) const; - bool IsWithinDistInMap2d(const WorldObject* obj, const float dist2compare) const; bool IsWithinLOS(const float x, const float y, const float z ) const; bool IsWithinLOSInMap(const WorldObject* obj) const; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 2e4116f47..1fe3e984d 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -8599,26 +8599,12 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList, { // use object grey distance for all (only see objects any way) if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), is3dDistance)) - { - if (!IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceInFlight()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))) - return false; - } - else - { - return false; - } + return false; } else if(!isAlive()) // distance for show body { if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), is3dDistance)) - { - if (!IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForObject()+(inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f))) - return false; - } - else - { - return false; - } + return false; } else if(GetTypeId()==TYPEID_PLAYER) // distance for show player { @@ -8626,54 +8612,26 @@ bool Unit::isVisibleForOrDetect(Unit const* u, bool detect, bool inVisibleList, { // Players far than max visible distance for player or not in our map are not visible too if (!at_same_transport && !IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance)) - { - if (!at_same_transport && !IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) - return false; - } - else - { - return false; - } + return false; } else { // Units far than max visible distance for creature or not in our map are not visible too if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance)) - { - if (!IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) - return false; - } - else - { - return false; - } + return false; } } else if(GetCharmerOrOwnerGUID()) // distance for show pet/charmed { // Pet/charmed far than max visible distance for player or not in our map are not visible too if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance)) - { - if (!IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForPlayer()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) - return false; - } - else - { - return false; - } + return false; } else // distance for show creature { // Units far than max visible distance for creature or not in our map are not visible too if (!IsWithinDistInMap(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f), is3dDistance)) - { - if (!IsWithinDistInMap2d(u,World::GetMaxVisibleDistanceForCreature()+(inVisibleList ? World::GetVisibleUnitGreyDistance() : 0.0f))) - return false; - } - else - { - return false; - } + return false; } // Visible units, always are visible for all units, except for units under invisibility From 129c0797a7cbc8bb2782e0aa336e99f636283635 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 5 Dec 2008 15:15:52 +0300 Subject: [PATCH 142/256] Save only changed achievement data at player save. Some code cleanups. Also increase tempory at stack buffere for utf8 convertion. It used in sql quaries log output and need have apporpriate size support. --- src/game/AchievementMgr.cpp | 157 ++++++++++++++++++++++++++---------- src/game/AchievementMgr.h | 20 ++--- src/game/Player.h | 2 +- src/shared/Util.h | 2 +- 4 files changed, 125 insertions(+), 56 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index c255bfb93..e4e26dec1 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -147,41 +147,97 @@ AchievementMgr::AchievementMgr(Player *player) AchievementMgr::~AchievementMgr() { - for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) - delete iter->second; - m_criteriaProgress.clear(); } void AchievementMgr::SaveToDB() { if(!m_completedAchievements.empty()) { - CharacterDatabase.PExecute("DELETE FROM character_achievement WHERE guid = %u", GetPlayer()->GetGUIDLow()); - - std::ostringstream ss; - ss << "INSERT INTO character_achievement (guid, achievement, date) VALUES "; + bool need_execute = false; + std::ostringstream ssdel; + std::ostringstream ssins; for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); iter++) { - if(iter != m_completedAchievements.begin()) - ss << ", "; - ss << "("<GetGUIDLow() << ", " << iter->first << ", " << iter->second << ")"; + 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 << "("<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 (); } - CharacterDatabase.Execute( ss.str().c_str() ); } if(!m_criteriaProgress.empty()) { - CharacterDatabase.PExecute("DELETE FROM character_achievement_progress WHERE guid = %u", GetPlayer()->GetGUIDLow()); - - std::ostringstream ss; - ss << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES "; + /// prepare deleting and insert + bool need_execute = false; + std::ostringstream ssdel; + std::ostringstream ssins; for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) { - if(iter != m_criteriaProgress.begin()) - ss << ", "; - ss << "(" << GetPlayer()->GetGUIDLow() << ", " << iter->first << ", " << iter->second->counter << ", " << iter->second->date << ")"; + if(!iter->second.changed) + continue; + + /// first new/changed record prefix + if(!need_execute) + { + ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetPlayer()->GetGUIDLow() << " AND criteria IN ("; + ssins << "INSERT INTO character_achievement_progress (guid, criteria, counter, 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 << ", " << iter->second.counter << ", " << 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 (); } - CharacterDatabase.Execute( ss.str().c_str() ); } } @@ -192,7 +248,9 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri do { Field *fields = achievementResult->Fetch(); - m_completedAchievements[fields[0].GetUInt32()] = fields[1].GetUInt32(); + CompletedAchievementData& ca = m_completedAchievements[fields[0].GetUInt32()]; + ca.date = time_t(fields[1].GetUInt64()); + ca.changed = false; } while(achievementResult->NextRow()); delete achievementResult; } @@ -202,16 +260,19 @@ void AchievementMgr::LoadFromDB(QueryResult *achievementResult, QueryResult *cri do { Field *fields = criteriaResult->Fetch(); - CriteriaProgress *progress = new CriteriaProgress(fields[0].GetUInt32(), fields[1].GetUInt32(), fields[2].GetUInt64()); - AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(progress->id); - if(!criteria || - criteria->timeLimit && progress->date + criteria->timeLimit < time(NULL)) - { - delete progress; + 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; - } - m_criteriaProgress[progress->id] = progress; + + CriteriaProgress& progress = m_criteriaProgress[id]; + progress.counter = counter; + progress.date = date; + progress.changed = false; } while(criteriaResult->NextRow()); delete criteriaResult; } @@ -271,10 +332,10 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) GetPlayer()->SendMessageToSet(&data, true); } -void AchievementMgr::SendCriteriaUpdate(CriteriaProgress *progress) +void AchievementMgr::SendCriteriaUpdate(uint32 id, CriteriaProgress const* progress) { WorldPacket data(SMSG_CRITERIA_UPDATE, 8+4+8); - data << uint32(progress->id); + data << uint32(id); // the counter is packed like a packed Guid data.appendPackGUID(progress->counter); @@ -577,11 +638,11 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve return false; } - CriteriaProgressMap::iterator itr = m_criteriaProgress.find(achievementCriteria->ID); + CriteriaProgressMap::const_iterator itr = m_criteriaProgress.find(achievementCriteria->ID); if(itr == m_criteriaProgress.end()) return false; - CriteriaProgress *progress = itr->second; + CriteriaProgress const* progress = &itr->second; switch(achievementCriteria->requiredType) { @@ -706,20 +767,26 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, sLog.outString("AchievementMgr::SetCriteriaProgress(%u, %u)", entry->ID, newValue); CriteriaProgress *progress = NULL; - if(m_criteriaProgress.find(entry->ID) == m_criteriaProgress.end()) + CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID); + + if(iter == m_criteriaProgress.end()) { - progress = new CriteriaProgress(entry->ID, newValue); - m_criteriaProgress[entry->ID]=progress; + progress = &m_criteriaProgress[entry->ID]; + progress->counter = 0; + progress->date = time(NULL); } else { - progress = m_criteriaProgress[entry->ID]; + progress = &iter->second; if(relative) newValue += progress->counter; if(progress->counter == newValue) return; progress->counter = newValue; } + + progress->changed = true; + if(entry->timeLimit) { time_t now = time(NULL); @@ -730,7 +797,7 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, // also it seems illogical, the timeframe will be extended at every criteria update progress->date = now; } - SendCriteriaUpdate(progress); + SendCriteriaUpdate(entry->ID,progress); } void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) @@ -740,7 +807,9 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement) return; SendAchievementEarned(achievement); - m_completedAchievements[achievement->ID] = time(NULL); + 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? @@ -819,20 +888,20 @@ void AchievementMgr::SendRespondInspectAchievements(Player* player) */ void AchievementMgr::BuildAllDataPacket(WorldPacket *data) { - for(CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); ++iter) + for(CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter!=m_completedAchievements.end(); ++iter) { *data << uint32(iter->first); - *data << uint32(secsToTimeBitFields(iter->second)); + *data << uint32(secsToTimeBitFields(iter->second.date)); } *data << int32(-1); - for(CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) + for(CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter!=m_criteriaProgress.end(); ++iter) { - *data << uint32(iter->second->id); - data->appendPackGUID(iter->second->counter); + *data << uint32(iter->first); + data->appendPackGUID(iter->second.counter); data->append(GetPlayer()->GetPackGUID()); *data << uint32(0); - *data << uint32(secsToTimeBitFields(iter->second->date)); + *data << uint32(secsToTimeBitFields(iter->second.date)); *data << uint32(0); *data << uint32(0); } diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index 35e07570d..6392a9fc6 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -28,15 +28,9 @@ struct CriteriaProgress { - CriteriaProgress(uint32 id, uint32 counter, time_t date = time(NULL)) - { - this->id = id; - this->counter = counter; - this->date = date; - } - uint32 id; uint32 counter; time_t date; + bool changed; }; struct CriteriaCastSpellRequirement @@ -54,8 +48,14 @@ struct AchievementReward uint32 itemId; }; -typedef UNORDERED_MAP CriteriaProgressMap; -typedef UNORDERED_MAP CompletedAchievementMap; +struct CompletedAchievementData +{ + time_t date; + bool changed; +}; + +typedef UNORDERED_MAP CriteriaProgressMap; +typedef UNORDERED_MAP CompletedAchievementMap; class Unit; class Player; @@ -84,7 +84,7 @@ class AchievementMgr private: void SendAchievementEarned(AchievementEntry const* achievement); - void SendCriteriaUpdate(CriteriaProgress *progress); + 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); diff --git a/src/game/Player.h b/src/game/Player.h index 2682149f6..9035b0c8d 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -245,7 +245,7 @@ struct RuneInfo struct Runes { - RuneInfo runes[6]; + RuneInfo runes[MAX_RUNES]; uint8 runeState; // mask of available runes void SetRuneState(uint8 index, bool set = true) diff --git a/src/shared/Util.h b/src/shared/Util.h index 0b93cc985..e27d34efe 100644 --- a/src/shared/Util.h +++ b/src/shared/Util.h @@ -287,7 +287,7 @@ bool Utf8FitTo(std::string str, std::wstring search); #if PLATFORM == PLATFORM_WINDOWS #define UTF8PRINTF(OUT,FRM,RESERR) \ { \ - char temp_buf[6000]; \ + char temp_buf[32*1024]; \ va_list ap; \ va_start(ap, FRM); \ size_t temp_len = vsnprintf(temp_buf,6000,FRM,ap); \ From bfe899b12634e6470054addfd91310006042ebff Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 6 Dec 2008 19:19:46 +0300 Subject: [PATCH 143/256] Some more map extractor fixes. Patch provided by andstan. Coding style fix. Removed hack from lava detection code. Please test water/lava detection. Should work fine now. --- contrib/extractor/.gitignore | 1 + contrib/extractor/System.cpp | 130 ++++++++------ contrib/extractor/ad.exe | Bin 160256 -> 160768 bytes contrib/extractor/adt.cpp | 321 ++++++++++++++++++----------------- contrib/extractor/adt.h | 16 +- src/game/Player.cpp | 36 +--- 6 files changed, 254 insertions(+), 250 deletions(-) diff --git a/contrib/extractor/.gitignore b/contrib/extractor/.gitignore index bbf017c83..908bb677d 100644 --- a/contrib/extractor/.gitignore +++ b/contrib/extractor/.gitignore @@ -17,3 +17,4 @@ debug release *.user +*.ilk diff --git a/contrib/extractor/System.cpp b/contrib/extractor/System.cpp index 30e28e211..3b659a4c6 100644 --- a/contrib/extractor/System.cpp +++ b/contrib/extractor/System.cpp @@ -16,21 +16,22 @@ extern unsigned int iRes; extern ArchiveSet gOpenArchives; -bool ConvertADT(char*,char*); +bool ConvertADT(char*, char*); typedef struct{ char name[64]; unsigned int id; -}map_id; +} map_id; typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; -map_id * map_ids; -uint16 * areas; -char output_path[128]="."; -char input_path[128]="."; +map_id *map_ids; +uint16 *areas; +uint16 *LiqType; +char output_path[128] = "."; +char input_path[128] = "."; uint32 maxAreaId = 0; enum Extract @@ -40,7 +41,7 @@ enum Extract }; int extract = EXTRACT_MAP | EXTRACT_DBC; -static char* const langs[]={"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; +static char* const langs[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; #define LANG_COUNT 12 #define ADT_RES 64 @@ -56,9 +57,9 @@ void CreateDir( const std::string& Path ) bool FileExists( const char* FileName ) { - if( FILE* fp = fopen( FileName, "rb" ) ) + if(FILE* fp = fopen( FileName, "rb" )) { - fclose( fp ); + fclose(fp); return true; } @@ -67,46 +68,45 @@ bool FileExists( const char* FileName ) void Usage(char* prg) { - printf("Usage:\n%s -[var] [value]\n-i set input path\n-o set output path\n-r set resolution\n-e extract only MAP(1)/DBC(2) - standard: both(3)\nExample: %s -r 256 -i \"c:\\games\\game\"", - prg,prg); + printf("Usage:\n%s -[var] [value]\n-i set input path\n-o set output path\n-r set resolution\n-e extract only MAP(1)/DBC(2) - standard: both(3)\nExample: %s -r 256 -i \"c:\\games\\game\"", prg, prg); exit(1); } void HandleArgs(int argc, char * arg[]) { - for(int c=1;c 0 && extract < 4)) Usage(arg[0]); } @@ -123,12 +123,12 @@ uint32 ReadMapDBC() DBCFile dbc("DBFilesClient\\Map.dbc"); dbc.open(); - uint32 map_count=dbc.getRecordCount(); - map_ids=new map_id[map_count]; - for(unsigned int x=0;xc_str() + strlen("DBFilesClient\\")); - FILE *output=fopen(filename.c_str(),"wb"); + FILE *output=fopen(filename.c_str(), "wb"); if(!output) { - printf("Can't create the output file '%s'\n",filename.c_str()); + printf("Can't create the output file '%s'\n", filename.c_str()); continue; } MPQFile m(iter->c_str()); if(!m.isEof()) - fwrite(m.getPointer(),1,m.getSize(),output); + fwrite(m.getPointer(), 1, m.getSize(), output); fclose(output); ++count; @@ -245,7 +263,7 @@ void LoadLocaleMPQFiles(int const locale) { char filename[512]; - sprintf(filename,"%s/Data/%s/locale-%s.MPQ",input_path,langs[locale],langs[locale]); + sprintf(filename,"%s/Data/%s/locale-%s.MPQ", input_path, langs[locale], langs[locale]); new MPQArchive(filename); for(int i = 1; i < 5; ++i) @@ -254,7 +272,7 @@ void LoadLocaleMPQFiles(int const locale) if(i > 1) sprintf(ext, "-%i", i); - sprintf(filename,"%s/Data/%s/patch-%s%s.MPQ",input_path,langs[locale],langs[locale],ext); + sprintf(filename,"%s/Data/%s/patch-%s%s.MPQ", input_path, langs[locale], langs[locale], ext); if(FileExists(filename)) new MPQArchive(filename); } @@ -264,11 +282,11 @@ void LoadCommonMPQFiles() { char filename[512]; - sprintf(filename,"%s/Data/common-2.MPQ",input_path); + sprintf(filename,"%s/Data/common-2.MPQ", input_path); new MPQArchive(filename); - sprintf(filename,"%s/Data/lichking.MPQ",input_path); + sprintf(filename,"%s/Data/lichking.MPQ", input_path); new MPQArchive(filename); - sprintf(filename,"%s/Data/expansion.MPQ",input_path); + sprintf(filename,"%s/Data/expansion.MPQ", input_path); new MPQArchive(filename); for(int i = 1; i < 5; ++i) @@ -277,7 +295,7 @@ void LoadCommonMPQFiles() if(i > 1) sprintf(ext, "-%i", i); - sprintf(filename,"%s/Data/patch%s.MPQ",input_path,ext); + sprintf(filename,"%s/Data/patch%s.MPQ", input_path, ext); if(FileExists(filename)) new MPQArchive(filename); } @@ -311,12 +329,12 @@ int main(int argc, char * arg[]) if((extract & EXTRACT_DBC) == 0) { - FirstLocale=i; + FirstLocale = i; break; } //Extract DBC files - if(FirstLocale<0) + if(FirstLocale < 0) { ExtractDBCFiles(i, true); FirstLocale = i; @@ -329,7 +347,7 @@ int main(int argc, char * arg[]) } } - if(FirstLocale<0) + if(FirstLocale < 0) { printf("No locales detected\n"); return 0; diff --git a/contrib/extractor/ad.exe b/contrib/extractor/ad.exe index 31de435c4e00f7daba8252f79a9703f9896b9ff9..30d3f314dafc36ed83575e1d99f9bf07e886e056 100755 GIT binary patch delta 35768 zcmb@u4O~=37eBsp*@aaXK?Pg|6k%0VR1{DUuvG!yKo`*kQW49S70pO@)d~b%FxKmq zIp(!@dC;=##ln2648%aw(#i@SwW!QSvBWZ@B=7G#_kvnI&-45LKA*pS?%tU*XU?3N zIdjgLGjl1v(4m-h*w_@hYsaXGnznxp8V}NmbkJ!2O*EPf9(U=o?aly|v4c_btV2LgJo5JkJT#2iIazJC|6gFx#zwTo9?&37` zN(1M0`M-?OocAvVQpI!lIUl@{lhiH2uf`RVkC&?`W*%NXrO$e3G9@;i>W4)INcQF@#&fZQ}~pLxAnskN6U=GqFX=Iy_bk=Iu+$!ROTTsUdP8~iW&8PGa44kvTWYYMQTt$+%muFCU zCTPyg9)1;6j1>i7n>~QEEeWGjk;}7=oxJykHHo}ye9$Vk@yLM7xAJgPaOk)2QwIq^KBIxu;FlyiX3KE3GQ@EA{MCmoPw zjb=f7wWF8l&l?v@OcuRHGtFY#eQk_}4FaEFta0Rm(kgq{0%r@c2jf?;d#2*$;Rq>L zDk)Q5Y|smhK7R!eF_HJ=Ksp9lnfhOMiGw*4?n0la=Hh!at^!lUvYB*@m$Bz4ccHiQ zL#=xrhH$UfnPiPet=n+e<7oLd`k+^jB3?@bw$I+~De=Fo-Y+JZV%5GL#F#a9{SPg9 zE6i0p8+;sw>Py<{Z#%lYZJdnq>o!!EbLL#$T#}qs`h)1WX5$%iix|V@^Gwj=qEe(} zi!@_Y#53mBzn0uC_*;$JaI^NmR50uRTY=#p1w{%gXUx9;C}}J3yItU{e%M)Ma$Y7X z!#<^hWLZ|`#azKhL|K+TYm5JsWmT4@vCS{H35SKbkQBZ7z@)R7mz3#;EJr4DDKfJ3 zF&d4sNPSA?x5{$VPj0)(EdKc}*Epi5Iv<09BYN|N>-O`RhNWnd@bR z5XwQ!udc*20YeVvWY(Ro>kwHaChMJ7qBE?S7Iyp(S%y+6sj?@E4ukCqq|wTjy$Q-K z&=aMyW2n{E#6{Go@XIGGoyF}yxj)xG)7W67okx6!SIx+VV!g7pWw5vDqeR1>tR|HbZ4-;hI_v6u+~P zIMzVCBX!V?8W$3Y9PG1p21ZKlUZ$dX^T;$7h^pnh#}<~josT;o2^5>TR!e8CukjJ# zuxTt9<<2AF>@&KiQ()0?sE)|9AYOW`(DR(G82q2}Ud0vfEK}?R-l|eq)n0fW>rMQ! z{+jcOFIQ*4(gVR<`dK@ITKns3=YvcvPN&hFnPp1KR8(&`7V#7IGkwAkNIs*x3}GaT zo;38DSB$FPG&CR4J)%D!%rlL``T8?SCckt38}BaS8D4}@HJ{O0&`WUVhfXHMt=9WE ze^QM|swp}h&5TM^8s#Phxd@u>oloAShrI`M?$XSK(g30Cd|o$!{_fqo^M&930_xX! z**%JxvJZqhHgIx%6Eqs$%G#1!vdo2XgQ*Hq7j=RyDM$Aqni!x`zMy!25_eMROH1TBhRS)O4 zUMMkD|ES#$J*{a|g6^za)r}q=-z+-22|(8@Q;<98xZ8Hi`Gc3odDjwCNRc?0YsvE^ z=gUw{Tw)43b8o9V=$OZOk6EUWw!)fV!B3FsZLT{ z6-Cz8Ho3K$axTkfwraTiD#X%RA(SFk-<+J;Go2nsj5XBd|C%s<2OSykiLi1z_3FOM zuekzkC+*Y10BK9B96x8W3l){M-E~BGsG{;?V*n9~cF`YtLDn$TpX zPh+V&>5!g*WFDQ=^I^Xix!u}gK+!bUx(MJg_p9`)o>9W^a%u=P27I}b6W|4R2$)}{ zqXOfJovsM{O?cvE`an>qaA^m9GUyrMD~T9o8dq8tVbR;jcy8wxYI$9T^V8 zqRI2fv)|xv0UK;IaL=nA__-E#8foW|i1-?x4a+f!rS$tgJ;-+YXP;oQ zn+ApklOr?^zx6aTG&qncyseFDvU#hPYz;EfSRF+iM@lB0 zIy^qTLVWfP+NZzKYb8q295wgvEf~w_-2Q38L)+=@{v(8t3zYSL-|x?V@g{toMM@J> z(S*5-9ta;N+6o&30!iuNp{>XcTn5XFPk)gu)%`|ve8fSgUupz?RR{9)XYpwLe zFf-Xky@&VcZ_VcX7~<<3Vd#*adzj99F%{FX!EV76`dVB8?9-(*ZFq243zTf0L9Az2 zdBP|*v5QF9?A%+?WQZ;7Ef;kUpWeByOoJJ%#%~6Dw~SsLo+8}XL`OzBdhg`(@M)nk z%2?P@RWs3cjq{dJ&}9aD`bl~`>X9BlKB;iT*N7{e>k`O%2MbGmtTHFMjtJe?RrViI z;Fa3<367>$4Y4JirO>@RW_^ry9z9stw1p;)-XshvrJs)OCTw=ni=*cVPB$HYPg=j71sI^mO_0@erswG` zTyCea)<=ioJapi?ioBF?{@2)Yn0t)x^o^KmeSk%mGxlY1g6c(9#~Fi zrvwRu^68@~1BLfj)0b0*dY$3|^zt+Gd`g6nvz2xl?-Km%bj$c~;qr1?HU1&vFbG#$ zckK4tUHNS}oj4&&s4k!t6EZrzy^QmywX#>1Q8ID95U{M$HgPr)7CuVrCe0U|^XQPt zgRLj9Ar!q&;n(VMG*fJfuU^rS9g(o-QA!f`prpJ-)8#r3hrnjzIKI|xF~JxI*KL`Og##!<+{;hUfYflI`95k+y{|(P zI*gTdW**&@8d}uKyT5y$GQ@Lo#G09hwHnOhbwHo_J2aO=Oa2bsz@bb34n4x5S$~JN zaOl{(phaqPzX2R^7g&Mja%jNcq1!lA^LJ=HhhDz_Z{6@~2K4k_p^64NpbRy(cl3DL z6d~{_8aTxy{I;2nnKEBkc^}<5rGJlyu=M_eR^C!b*^~+0>*gvG9)EM?4`Pb%ocJ29 zP~M(P$4^}+ESp15PR$Y?eUuKc3=}3@pffBc!`_Ga1i7ae>O7NZsbvze&{G!wK}q1y zx!S~yLyE73dE_c&qpIpsOg>mSu9T3n6kqX^oJ;b<)HgjtIC_!JPwxZ!^;mjrzk(FS zW|+9m2)FRQ?s}xnMk$8sM4oJ0b%FknKCpB7Dm4FDp4`Sj@U&@QAb(o9(D`B7En}eY z-70!dMxs!$imuKWAgo$NU&#m-hRvo&Gi<_7v*_^Yshv+l3=w)(hPdK1-2iq&YdJ48sg(x05TO2$` z8C5U@t=Bq}zItzPmspgry;fde$Rq6Cr)d4XF9Z!+st8C*1&@-9Z|oKSXJMR}R0)&b zeJR~EbFT2-1^U~}(V-en*J8`hhlC`VLTpEV=j|+d06j^7Wnmvpr!!_vo6w+ubpWFk zQTslxhF%-e+v{SIZ5Mz9PY(70q#`VAH#}|Uksw4kMykXjr_-ymrg!~g8rQ`}xOT9I z5WUbJ=#1H;yK4U6P4_@`75kA4x?}c`AS1xekL78u*Gv(p!cM}Dw2{l8S7#6H5ebCb zrH|b%Wz*=$oU!@|3e~8^bWM(*K9!@g?u+U3IX#4h)9C&jix87eJI)F3e1p$Jl@>c> z?WM*isd-KhA@>J5bI#!I4SaxqOIOA-&;Jl#Zc(zWg}yjvoZz2MFU*ND1W#2;qnaz~ zAERNpp#omxb4~p9KyD8&-xg4~VWIBaVM5VVT9w;F*s9VF=Oqq{N;@#>tU?{WXYaXV zg)LL*{c}edq_lS0=N_Z4%#9K7YM2{f$VJr(9ztYmr&8g*p*;;#AltX&11Hn~0fzUK z($v@j-jq&dG%u*VsjYxwB8}J~MPlz8QHGs4J9Y)K${jG2m|f4AO3-C?x`s}gJG3a{ zFod+gG>gkT`?4CDrl@1?6mk%Aqq*^&&&KK-XF45CXJM&)U5pUYZHP*0EEW8afCVTn zpKnxi{LK|3tXK}QJQAG5mU228G0R{@Hj*EdB(Zxr%oisU-n?qc0$0$O_#4a8KFYN1 z=RN6)-ogpvY#{bqj5gqa$m~PTUaD!;JeM~>nrt2;OEu+Up+5(P?iwBpjK@WqeBa1k zr#ZPN)lp^{Sf*kSw4C+9%JB?%|2`Aq4&wo zKaom9O7!MI<#hJQr1lo3v870J>;jY7cbPY|AeQLA=-2m$1sy@jnj>a(sV%s4+bU#V zr2g}Ud0BXK`zF)0c|8^@E{Ni5M4k0G1?kv~afXj_7(U8yxIlmPQMh0QwR!NQ+iK=VfjD9}W|WC$XM)6?aD3iX~#=OC*+!hpGh5Al3|LpuMHb zNIPqTE={GM&mT`_)4&B`B#z#*z&JDn5qQ-KY2#}g5iCuq1*a@M$irfcn{EmMqp<+O zDGP#Awr)YPsSk!BPiM1(Ycy%EEipZZara=CFl%6BiG{t{Os_8JA!u&UjthJF7qlU= zXF0-j(~@ayZZl0>7*3|r1q+Atimj4m5aE-j#R*6d^MOkM)@??Ij(O0x7moER1_=wB zLT@hY<5hw*`*u7Hv-K-lthgvD<{YG*h44!{h{?W#v|-Vs zwn4!=IX@l8bCBNoo}!_+P^X&m)0vI>E}BYmXzrpRMY+)U>_Jqut>UTqNQosTZhNd2 z_SRKypnRPt<)~&+`_A3A5RS2JBWk3x`*M`=3!27;E9gepv!r%x+iRSv52#w%@+KvE z->kcWMJ(9EOXWfX_0AgG}v4OW7&K3 zp}YVxf|ljoPma+md85eVwEyB5GKS7x9Bz!CjZXbD8jwq$U%b?J4Kz3`HTPV^lPv52 z4P3H8_@R-$vZTRxkR4-?qAgxEKx6mJxfDd7ejpcT5`R3<6B~2?r87wqeQ0Sn-(Ss8 zpKbaeFM@TXo0pag{rAz456&Zx(dQogNN9eC+Va!MB6={tf6<*ii}Q*;OjH5(p?Kc{4M(^h=qYAo`p`+v%O!*a_Lz|2%C?> zJKLD}-RyJ9@&6BI15HU~SD+s#7jY`sX| zS=NsnrstL|@;*ZAAG9nzD9QG3#p-IgN-@DxpN^%eVZ*_=-lSKTCkani(inR`@1S^<-?JGR>?vxqn@A&d+xrROKhk&X!;^e(D*7Y{ z?L~9XhWi1va0E51v0h=vkFygE@H}?l%pF#u`CcMc*-Ly@Iml5)ge(wTF;Xzyq(84P z4!roKQroELN7S~lJ(xRN*+j*@#q!z-*SXw(Tp792S0E$ln1_3kAUf;eG_Ok3#qiVJ z565@k5Tmf)zRk%Av6kidvK3T#Bu;qpb(;7{58=rlY1Siig>J9YcOMx_y3)o+9u~sS z(*=*t5`LLak34!+k$3thN&fDrT&-L&?V&ehOt zV)9OlJ8ch}zk^P6PD2C~OW;4S*pcpWruyxHHc*@o&(dRdZTwLzpmOS0l1T2S(@Lt) zT({Cl!NzEEX>?b!I_IWz@g&?`6RS8(#nN8F_Xp^%(qRGlFbtUT$n^ak(UTbqfD+3t z(_cz6gqQ2+_;rJOFI>dA=8iswA z9=F=$@WLE!e7&;3HCYfgzDAFUUy$eMiyH=#GWyYm6d_+nySkIQKc^e3xfFu2Y_4sv z`@(Fb)|rjdb(IgeZwZ1K?~Ox=pnaXb@MN&B1^uWSm)Zer){UEB@u0__94SQTsCLs5 z!Jw;LwkeB{Q}j4Zz^{I@wM&y0w2eS-BYUFq!OdfYuDbzl^nqncg&*NpH`chD9^NvE zY^L6lMJUi#&XGPRLaw$l`suAin4qPfJhM&+*H&7ets#Q1mIgkbOIj)mp5IK0CO>V~ zJpGJWGw@lnW(%G_@XUM8tT~Ej#Pep&3wZjxVAho4c^l9Bc%FUHtm(MTtl5air`)X3 z{>!YnvfZqyd&#Wn@v>R7c&AzOJ)VEPV%8kT^ZKi1&5T`U%^W=Y@r0m$44wrqnmsg+ zzDPH{xCm;X^~Ii~Yi0LsKY9!cNB8P9ffyu_HF6_tsT*UQ!24|68Dj5Hm#pc8GTeDd zLW$X!tEEG?-z1a{+Of^=7x)g&BLy`%vzb?8BtmG$}B=Q(jQ(OP_)qpcOmwECi*?Ku@mli zeF1M9TaD^QqZsl0MvxP;wNYR6<(q~mztWA}fbzL`xSIL;?ERW!ptiGG>$A5?)Rrm) zJ{12A4*o{q!!_S26tqt%6lzdKJXL)eM2gO}QTc!5fm8S^8+UjR{~h(=KX_>4;6pJ& z;Q{rdK8&gnso^#6BF;GPwa?yjQGQCF_^IUW5$N%M8Gt)2N1^w3Rm9LKjQpqGqph}{ zR~PYtXrBSGKI)5q%z!%nUx*RP3~=7R_{TKd;ez-74i|hRR0hN#b@)Hz1Ztc=hfMV; zy^Np$?f!b#!F(pwF(@!~6%*d)V*+0OyhBK3;?Jmr(v8&m`T)pJ@$2^#ea$xqN&B}l z7>_GS@PW4VhfPVVXGhB6^UQD6xRdLlH+Qq?$g7q!dAEgm2E$;s*W1JE?QW~L;cxYV zj z8N2w)bHGMbRCAm|@AFhue61sxJq}QvCIE}p%Kx$1!?@z`gVt!A!J>xANmh z22Bnld4X+1<2B3+Sk9^t3z}G~G*MH|2g!MqL>DD_*TnaM9#IF=ioKA(P!%)po1#=jk%9wI`r{Mv7-x{#`9COt}>1e zWH#nDDcr`HppCy~_Ytd|2pKr8<;=d6oKH7ZMhTripmmj@!svY3SlO@W(!JPl@PF#O zvHcOsly$0U9NU~?aN0*&*}w8JpEz_|#NTWfei5JR&Cz^Is|t0_<8oscF(oLz&fd|& zy6P~CuGK-V)dsN!VHaFQGT2(Uyc|VK&a?|M?(;hIQF8nZE;V%H9_{c2C{deNIAJj= z4_s^vV8U!SaB7(1<3OyjGJPto-4iBQQ)%O#u&!6K|Js9h2hossRtR%D)2;6W384?t zz3=qu@ZwUiWnn4(==paB2>0hx{oYhBV=5QpEIM;KP!Fxz;N;fZ8$KJyhe=& z`;W}xT|P2H5yR4EyTh4SPseIJ9ODqDNh`s)aLsFF4xYrC#m2J(HrQL}ii5p}$2s}9 zS+R~{PK#qTvcJA*j0Tq`0+=r+*d+UF0kE(t?08(B*{o~^tvfiNgR0YXmu}JD4=(Mv z7==!3ODxmrL+|$ReQncN&9eS%46kBj{ioAs-t9-KX!W}R9d2^9VPxNC(1v&K@9>10 zb7aue_XhOzeO%%1I;N!;OGHtfhP&@9IivE4_a+Dev(Ph#iUhZ%^4P#a|gMr&^27w`>}WRkDg*DpF^o}TIaXK{sFFt%JlK-jsc@o zLLmwvEVsO&a#bkpO>(iCo zf=EuL)s@`Je%=7qPRiLhqVK|WiN4q)2UX z$e$wW&uE>KbF3!M&$gA1)-u#^ej>XZ=Uk44wqXlm{WuiE)(LNQh{am*%S)&DxXJN# zca2+XDmoI&zQe0dL%%;9hnqFiQy{BfdcZPze%-PIT`fyF} zxOV_i`uo@h-d`->{hY6CfSvO%D2g@aD5QC1D1`a@M}VUW^JV&JP4^D-d2JMYO|RAT z>B9wB<1n&Ep1{KG#g4k+NXX!s{W~1>vdimf)R7Tg6*2!xtVgV3NS+}lPM1UD9qrwy z^FT`u|LRME^E(gc@A_o}f88OQp4$F7?ek&xUi&{YYh;sq&*#`o;2q1~M*+Kz$M`w5 ze%N0CX3>YHaoc%O*r)3~%et}&fhNl?MDm?jkY6YCCg=AFN5ml>Q59)pg`rqU!7 z0fQrNoR0J=JlpWBPw@!*v~0YG^Jj&(s|s&#|M}~VR&>_<1@)*47w{Tf7ulEB1+Ujp zs}+wHSpyzFJVAI&ct(Cf*Vaw&Q(3YAkcG#Fr{D|vb=`ClO{0#Q1lxF;eRP~KF`m9~ zw8!9;IeaoYph_m(9O!4;nO7A^wBWVN<)t)_N(X8yd5rWlu0r{Ygyt$8at%8%U~r(l1JS6g|7SdEqL zR#&Ae&4(Ldrwj0b12EEbv6+Dv2=z*=M(-R&)lwdx7x`QxVF5&IwsNN6GMfE z##OF3F;XCp(lXW^LL&9-Cf<1wSk(~{D6Tm*X2WwKufsXy^9{T6WX+ltVW%{X~1mWcb zYW_TsETgkNA8lCqC@MHxWV@xjioW!D?|@VQ@(6A^jN>IxcJ?4E8%fW89$ZAB4F0L< zvTLF0IG=`0cAT$X?ym?@_&5MQkFTwTPsf*l-!>5x8LsPA;jIoUHxW?2e^+&RK)_^K z+VJSg(>)Yr*Modbcb)F7{cV&+Bl$Q<&yMqfqUf}dmA{7 zU&eIG2P~=?(CKmXfiEq>yOZb#U+yM{EAzk7>w?BdwKKz}BI$~3yhnb=`~&>zj3~PK zoXOiuLBRG00q!XJ;kn*vmp+wc=yhM4F%4Y|K>6)1e$Jz4=;D67?{x9`e|GUzAfSsI zhtpx_d$)D27hQb5zxUwVRawk%`r>(G$1Q*;owU*F^NC)uyj9(Bs{1-(hT?trlu~%! ziqt!AHTXQXo^K7cY-TRz#8udu!Ag`=azlKbPst15C0^C@6RjB*wqQOuRzl=DIB|_J zRu)6oech*1H0rpL8-Q^yef#TBa+-ee^#I~c<*y@(RQF{%ycMwp5fg_2S^y1h;Oe4A zEWA)E`;>lwcH$C~Hez{4fMy>Q@x%Skuw`M>BT-h^;8=3U>5+$WW<49{@VZXaWkXdY zyG`{?8Xqccc90ZnMxMsM-GNd$z_E>$o0bp02_E)6$f)>mTzPb|hMfZFQURO>;03V5 z$lYmm*-+};5Kku3i4B8@w$jnipZE>?n9r`FvE&#n_DgJaBHjIMRQK!HT(YD@97n}8 zAt|z0|}xVEy|HmH4A^-aOzj^4_qCIGL3Q{s-t z801`@`1Z}pMkoae-DG{Xx{SEim903X3t^F!VyuGrx zTqF*rAAi?h$R13azuWxZ?dV(i|J{xz{i4{>tZRx{n*NJwN9&Q@Xv5EDJo~RHb`+T0 zjwW%G|7u5hDQr_bUg3B`@EGy<;?d*L;Ay$0*inut%Dll@cx-qIeo^db!>_zRv7;N2 z1hxNUM=ziP>?lXxcpYgY5@tOA(~dU$s@PGyxE`{b?^Y#QQbHLFx*{fRAx#HXA4G%%Htl0Num7|E;i| z4HDk#M|GD52oEIC$V-uN_0VeAti8GhtNIwG8*19;sp^ShHP@^L+bTZMCH+wN*XTod zKl=2gp~A85^rK7R!)F3P(Hb4F}hl=&8$#41Q>|Ms%FRoz#HJ@ zpbSlOXjBzO+GyL)N6ae}>Qv9RS%Akq;;6IZ;(}wL7<@`Tgraft1j@Fn)r{cS zQ2N%@NI@GyzrQ+2$Qwp|o1TdaJ9JxXIun!7uz*0_7x$@?96A?umF+<^E|X+uV{H9w z^?Ypm_om-BO&$CZwgOyx>hprwQp`~{D;x$Fhy#4tYz2^8h)!bkSr(mhEuatMQ+MAw zeAb(Q#@O?v9KBGF?uO#(N;dPOTdsu}jVP-K!jDCc@x@DyF>vhH=%?2P;Cr8&*9Lj@ z@5PP8kClUesTYKUJ*n4kV}%tx>Ez#5=u^YTYBH?s7(MpeY*Iq|H!l)~_Mn@Z-Q*1# za^qeh*+>g+BnV!{%7ZuhcnBB#D$oDnO@uGH(JMDs;e>2{t6AvTjlSHvk32}{{P}@E zLukmY$xX%xp;}mnu_VlTU(KZw>w#1F^}g< z8!#_*x@{O7g8$_x>;_b1>vR+F+d-?Ts?(*?T-g-56?p^~7vy2e_;Q&CzHJ-Bc^7h# zbS7@4FUftqTKM$F`qIzjF~TU{r~Jv{BEGAOs!~lWR8Ykd=*YGRpB%$8Y&|A}uSFle zl27rJE~?5ryM`~v{i~oPYRVfx#G2=q1L5%6&p&->^o*}9^b%_;cu5{^_I*DQM6xT+ zVJi!yUU^!pD~6X%U?2UZM3>hyE2k#vvjd!PqpqA+a2W(=b%^t@cFpfCE5>RHF6Z6K z0Y(`xGI8#q?)4?l?j&ph1FYZ^{wYKad$X@bQ=G`xKaWo@SCm zls?2aEel<9s~+T6_7p!E#KRrVYTtDB6KwmMDFzLeTXthde6D1b{mY~$x)Wn&6^am; zSTjK_#h@h{c#sze81l9;#E>doiLYMPJ5eETT$5{%i)48a-@7=gd@byGZdveIn^Jd! zbgMh*Q?&FiusifP!&v>HJlxq~As;Iuv61Jc6~QFD@5><|dXSqQzNu+5 zR@_dBP1Uz_im`g9N~#GaeMyycDVVs0PlNWY>P5Nxd^yQFCYqTVH=qAK`2=$?0iWI4Ry&ITJGLb>rk9caiiS*I# zKx*Gs6S zcy}A4S&U~Np2K+bfRFHpqs>JKGaPj+Ui-0Tr9=WqPeHp<3JxH~Uh&Z47){UpwpCan z_`Ix!g|~y2tdcSU$UqNUL$EZ`NV0XxbqUFBB(Yt?U%*-V6kMg&dz_3i#4_Ux(pN?@ zPS_A61@#~iU3WaMmRptbQS7PbrF(mj&?LhEF6bdP{$^1*-1=Z+j9B{&d=EZN_UCY% zjEiXoHZ(|)+_)@*y{i)2%@jWukFw!GQdJKUSk(1zEeJfH+$2uWi(j!112vk1kS;kc z!{Adg4T&}i$Ju!lT?zt385b)QnMJ(D>h|&*6Mkr&pB>=JNgd&tO9lJd5qbE5gV-W~ znv?bT6v@lV#y>A<35gPJBujCG6n8LA0fqt7E*&Oh2`QF_3S_MI1?Wi0A&|TdW?p^~ zc1B_X>F4|Yb7;2hFy=Q7?d3rZdR6k1xo^%(-*}KwUEX;I*KYD6Z2Ni5?f4E~8mJ|~ zLevY=L@k*ita(A&rX`z$&i*dTHF9!8kA&Ul~7&-C#*+xsa8j(bepqSU9UbRzrYiL5u37D>hDQnx^=%@@TywixmbG8 zlXMrh9+%2INgp5nM@*EJJ{Ps#&y)6hlHUEtA6M>CHO8?`?ZpF7T-u%ql2;np$~@_o zCmGS@>T|Yn8A9Xq<#FX9RGbU z5+|IKq!up{FD#Ix7(KaH&}@~S)RPEd!qfXc(33zSJiSml*MY3^vP0Zz9(jEQ-FO5UD{~PLvuNU^IlECO?s>d!xat!Y~JnbjB#yO=7}oDr z%`H%K32H7&&6(BQBsG_$<`UH01T{CLNX^blgrEA{|qB1hEN zy`701Nn?lYbC}Bc@>58Z^CeTK;}yH&@3y!UK~d_etG1$TdHIx_Kp)k$YANCx$EW07 zKv+E_L5|_|SvROj6+_{bc_?|_tkM+w6{bX8!xf4+evdp3N|n}FdJpav*yr0khho90 z1QWU5l}}Z)Yqkk(BHo=HM!cX+#-s1ZxYW=Ux^}13idTo7TrA&cgoY03M#3V-!t%2^ zWNX+J*hbM@fYt>0)FpUpGNkw@N52o{a?A$l!ER(=*TchL6Tg6!%C6XeKHyrd^h!6< zPdGD2`m`Gf8N6?fMl(Bm=CQ+u+YXPFA0Ogs#q!J8o$`Ne=k#OWlY04)aN+IE(gZ&; zMeyAxZS^Ay#(e>%vTxL92UhVQ8V{KG*%)W!txNdZI{ak7Rd^0ddMuBMK#w3Y>}ZHr zHV8g$9(XK2CyntZ{+$!fg3aux&&IlDv;sEIpG@)QKD`{h+scwrD1G2hf-J*9wg&We z1#q!MqBr{6ewqju+F)gWKu7Q+gA_yd&b5y2>>&oDqa3F?rx-$b416dAbf?+w&8$qC z(UXh`?|i1s$+jDqprpBj?Tw2Xtac0GJ<0GMe~G_nL+pNe zLPkb9OMFI(3nZa}V~;dDkc8`;SA5IMq^;p(aF<^$%5nz(*EXuv`@Re(8;Iv-tN~Ui z*#?sS!-(I$2i~*b)Tmn$8qv-L$aRP6Wn-0Fy2oaP0u)C0A2a!-OUkmsv zzaY&WL;?+bbLZnesm@*5AQBULd!Dpk@<~*-cA|E7vl$mUaJz=h{8IV`HK!_DK5b{E z+@m(mXrE}?=7VLR+@N7+_&x9gF%bN|rD3 zV=`+dzX)r)C!Sxse^5Fyn9L zMe;$p`VExly|_0owv-={dPNdr$K~&VX|a}hHAv=2(mhVO{xAZztS4NT+sgcws?4$D zbMZcMB-ePG7^5T{7l67=+89X&cYXCSh;#5ptY7D?TaI3Jx{cDwND|tMLwGl3|22}$MG3P?j@(BykR6qXf2a)Y?mDQP8s-2yMW-;;$x9mhwir;c(aZR zjRV)Gkdi8UxX<3vxL}7vhUA9z#V4eDhLiE+wDj0;vUn(O&!;pC)&fgNOv7P&)W@hhjBe)9XjmFv1Q=zoq==ttLBt^ z0ax_Umu4NmKtg;<&m#kCc(x-%La~P9v=!UH0Oqt}yYe7-eNgALV5iWo7(t zPg6H#UT$-KzLawwd{mklP5LFM{mEc2b0`akic(i~qt-dU0r7(d_AkJ26|Myf1~;|x z{$y6}uhi*UDx~+LNgvW6eG^T>l81nRy!SnHnbl?SH6X6rgABgf?H*@zbh9w;I|y?X z1bOdnj{RH7?TVMB@i8Q%=old4I&SDbD8|pAIt$yYfKIjLb}Ch>kYmpy3FGBHbQ(F) zD=}mZ%x(9$t-NiAkA;o5Lbyh<6+p|*cCWV7CF?y=w5F)#DEA|}h+g2Z6F7wXlFpIh z=13P~h;P^^o^jUs%4vE>os|vZS>Mv%$msMI=wL`zSPAU(BQQlyX( zBuRzNwX^ z9CJNRas=!I`C{BsFTFLA_`$T+jwGW=grtileMX*wtTDa?nkxk0Vc#EfT(^8A$d>PmLmDdJKUo5?k>p+W9&!Ud>sjZ|rGdf0jvC zN0AWnj^rCpVu**75>G}ayat_-WKd48M zGvT)*@b!tKms|T=75DmM6@4v7I_r#V+Xz)%+YKqsTc(1~Kw?f#jnkxHVqrF36Xgss z_!LIcdZet-j!J~q6hdALmq9;bXgLAc(I6N%!=Xc64=FGeu z!IYyv8e^G{*Bw2xsGhd7p4o=5g#sa8u?SLPKgO{O31hxdWCK zMkV^UDk*3*0y=9xm10Me&`c>t?TVv&Ci@5qEt^fonX`JZ$xmrJxkfj_VSbYrwY%N? zst>|OhqTZ*am@%Yx(P@ssOAZ2B{Q2b$7QK=c&Az}vp>uoL5frINfZm!gPDPmD zTm0}ijRRLgw6_$9bCq6p%*R=-oNti7R6ugRFS2)CjT2Rtc!P_N`HB8ZkD!S`N8PDi zuB5vs_@!G|KCUdIZ!jOSf*Y^n$SbtY2lRgB9J}HKet=QI;jTo^<4k@htNavFSoXZn znYd@wztyOU87yAwX&}2YtNH-vJ+QQfP9b5pl@|`+uiAc`^wfc=j&J!1w(h z_|H!!Mz7s`Riqq|-kVH@cyTAy74w>OZ88~#P;6K#v35{k#Ho8tTANDl>BMj06g=PP zDJH%qok%5Spn0c}9^|;xKMm2FDrrg@SxRE0_tS`JB1e|}>(PHK@h({OHR62MwkY5j zuq1p6eS5`PGfS%qvemnY%hQ#shWJ}07kj%C+*Q)RDJ02zVs*Q7&eE%;N2ie9U3d%2 zGn5NJ;x)vxtE631$VBfNd?BQ|@$7h&M5dCSMQ;M+4AHR7w~N5R>>6bcQxMwLY)>4Y zHuOf+Uo>4jrz9H2F3*E?lm<*A zp+#)ySk1eB5b2B$A|dCQY_P6v4`TOLMu!o&;}{nk|I<8&CISbyYio6BkHfu@{TbMT zG3jSJ1v<8y0*@y&YTGIJv>zb6?^bA7*&{E?vKf3Ntcb03@9vjwS;+2XnPh-(m;Knx2jDuHvQK2+N_#WOpk80@12i<-r5CR?R`WYw>P2^BI^@PXe~ z4@-DkDxHnfksEJGAI*mJHb_6uCX2~T>E0Y73jf}{@5dYxMGX7j#1b|-JIn0ZH>G~L zxR$WBt!4@I+kI(UVPu@mG(b!+;C3nC zp8ka#C_665{$@;i{I8DPEa`Qr@IGQ1z6b#p(NjFdbqcO#_$gO1vazPK*Qd$F$4FVK zp#5vP^!a@xNqG0QeLe2S8HC_^Rf?TY3eeO$^RWl0lD?WxM&jkOfLNClzoJn8hsJ`! z&=!Z>f2zDSc$aX`lNgDS8oEEQGuy zl`kUx9k{w*7Q}>?qz@JmQ(T*d#5GTXYo2B(UuWN)K*4QjUt5+U?=PW8Rk#C(RrU?< zP95S^J9bDxc_heR{XQTT*W(tP#y~0e@t%;<^2m@x)n(A)Vv5*=9YM_wtO5LS(b;;@ zaRKK;J3_sXn*}4x9*po?=J0LOuT)B+ca25Bx(8i zfR2liQ0^NgN>>(>9>T#2$!iJeEp$B~g)bq~AW)Ak!Ld%K3TZFi$Tlq@Zwev*lFA<- zlLPcT9M`DBQ6z4;tT4(eaP%CzPZE}r@KK$i9C*L&L##|t)3@xQR@RKz5$v9on`BG~ zyU1fn4ZXSSdw7A^{sw8@Qj+bZ$KMJ(q)(PEFC~GUu$|cN%K^R$;E>l=j1)f{ee*%` zMlW@^)6)@o-i@)tX^Kxt3XF?romJjcEIpD>R`$C9ITI5Z|NYeC_xP_0O^c5i#MQH$ z^Wt#RIZ-JNW>WWu$eVpEP=OWG`A-)AnT4NrhnwFF1IZsBB7^;TA?wQ5cuii2Z9kv8 zhUcXL%gDf>UC>T2B%PrD_%SiZy{?GFXMfed8ka{M5eW_y78s9j? z377Mq#(+bdjdK3e*zpi&q@4fMC0_tNobXS1P5NdT>1jyBjwmkq0^iY9NV?@@lrQg) zEA5=;iXEetTBRwv+gQ2cS}M1q4R`wvX2!K%?9_!S1^~lA&Y2eE^3^ zj7g9V*-4M0d4(8Bx80Mh_bjP$T+Y*u&tzYJ!N(C_+$Hi$K{$;#4s@h48pm2$6e@`I zrkr1ca>ay8IV(vr`BvJ#lJxcBSDaii zzS60c#2;tZ7gv%#eTq?q^UxS}M?H4T6S69J0q(vOOW~`?4B{oNUIlfzRob?SB=y>c zog{`V{w9LhvcE6%)TLx>D)FfxKFK;L2@fMMxl@|=Fqtgvewf^+9S%>M4m;o{4Sa-5 z?6VGzv~rN#b$zlvPbf=nEt~ykZSpNFbALAUDWJZ2AgrTR&i8XCGYh*eRX;*v$!pRd zkC0lOH-e$Zq~J$Mn8Y3>#bmy;r~pD2N2Rg?GD0A9UsVC()FfF-TMchBd!J)9c29!m zM(N!m5?2J-YT>eF*a*SlAEzNMzwHqC!NtZrk2$WwhWJDtH7?8)Z&Y6t?!Ymhq9^+mgez#bL%uwYpg?$B`13d*x5tIYOZ%LptM}0-uq4p%7))Tc z)VqY-6ZZ4tiZ7*jQgHJROon|0rj%|Eg zI#fb>b;;*6LUY<_m~*9{N(dFs#7b*R$slQWDS1Zvy@;4h8idb?)viY@Kywl-u#l^` zMS~bpUH}V4GP_x)k;W90jl!sr(&xn_IXDL*jq4$55PF6Zg|!wP?Pv6HiESYe^qJ<1|dj zrS%Xg)gpCcbiK56Ein#I3~o=h3}vceQa#Nvvy{9Mt|dLXYd!++m`Ks9 zImr{dj$xcX`!VU8wItNgg*T9P!KG){U6Qwx1clB6M6pXFcs*6YtGAStKT^jEj!2iC zB(bA01K&8h(-`X|S=S+&W|Y>gBYnCAx&C@!(J1}A4rQm-5$`S+5x!Ps>(p{J4BoBuJo4lOBo66^5);btEIj!_>LQ-KI=*M zAv_d_H5iLE$Y;#WKL_)2Bm0fNN3frjYzVukyiM$DxI=(%VK1~nmMM@G`uG^8K=9XR zrSonW(<^NVqtzHK0uhXnm znYo}qR+!>rvUUE0<7A}qc=4Sb>N{;aRDSnOGCV<63Gv0!I{vOM+Om;MAw~P9Zp3vxEbPiBNxVOS zN00D!gL^*T*{Z?pSq ze-nuvquE;NDN09RhWNwu3uWH)s`V1!)}>*K$1 zq~h}#sRKo*kV**@9(7BBlu6-HPb`pDQL?DVSP>JAn;Fi;&Cmv@jRA8zCe69_c24Hr@cI2Rf z{A|%Gc?*kC;M)K%=RY_Sm>L(n{YigJ?syB7Jfu8^*TP?`UbkM_xtWX{!`lH~q=k*+ zl|iqsdPb0fI4tG&6t! zYE8-lCMqT%A^|3>*h|BbdoMU*nAV|E10{1eGHt0DTPjde*0exbL|^VkMK*}Fw7J{d z&4v5Eq?CIYd=elxTug8{r6fO3$^K3C5UA@U z4A=c6{<@TI{j#Emabb@|W)-jwSBE#$rQFun#zxBNF{0;HHZvv$kuCQ==R{JBHr+o zo9?+EyL1e<;suM!rMO;hJx#Yw)Uo@ipxH&v<{eFRy;R(`CQUSdXu&tliSli?*68V| zS=vOyP-pX&M(ERx;|6l~2HYVrk(|(Ph}d+1O;vr2RML%;b#3n)+g`!(ep(zmzyfeL z<eb*k7p&kfPp`bW#ZI9jP%cziGLhq1$=dxc=B~N(|ukUsko6!VwrgP zb@o8ObR;c@=hbv46pPxac~M9!!k!P}i`Utldy)`4jcA+jZe$S?pDmTg!LH_tQn9#^ z&E{#PqOuWhZrocc-f3j}*hZ1u#Om1B;$joa=QU3W^&z&6-}98wbO+snI z@#A6kYq#}C+7aheG10tugQ#d`@obGa(aeI~zbhhLcdGB-io_SqECY8wV%}iy^FOW^ zH{W0ZDUCQ`)}EpHdyxbFVYQ#6DRk7)Jnt6%9vr6oU8kGq6SG{p1xOPUy0KG^r;~k6 zabn34+$~KN3CGw}aioP^y(byEhORm8siO96_O6okC0i_}y~7$NXeiTtvH0*E)^wi| z$v{$F0K@Z>q1RA)Q-+9oi@gqmp11JCSTDj)um^-s3!c^H+Le-HEhSeeMb7$?Xhu^;?>lwP6F`B*C*2hQzUNe!L_?}Kw7v_mU-ffqnEnA;&zP3$@k z(TT{DY|7LCboH=1o&!eGBe25Bh}I=J7ERHcqr{q%Oy%x&C&lTY*nN^MV`bv2lei7s zZFK$svu<|C7~a9Y=6vw5aZ)GiVEnr@(fbMRLmx{M-e=f85Bavb8oLEyjNq0g-aEry zUgG+4h>^`7iPqv z6@%1x{7UrGb$E8>cniKZUdO-P@GH$U~t{KM_66J_J) z_wF|ln#H0EY$0nlzIcKCg}Ig#;;T7UF<{OYhR@jrRw0&m;DEhlma!aD{>0#M? zX`(3Y!M$@|akz&?PNK$lSolxRi%_ccR5z z6|Ux3{PZ1`Q%+ap(t5@ab)ej30p@l8DSzA3&E^Dg)bv;JXG&Hi<+7jI^LwXGybwhPWyPF~1g2-vIt0z0X)vn%Z zXS&<2!QRf$R|UiKWaw)(%(fbCzuPd^-f$Te=#mP%0rW{-T`xLzC=jMfZ@0<4ZBlxB zrfle?wBMf$W61DLGF%eUFf`#UrHLQEq{x{^NcIkW{-_c^`>1%QpZTQp{E=F0_0x%n zDVzK}4nOi@8~QLT85t^sAGsPjiy{3MdZ&SOTSzywU$868J0Kgb6_qwax(OCX7*A+zz-8=}b2T3a~4O(qDYg8U~ejBnZu{mooq#uQv3#sLi+Dk8A zVUq*9#ubhl(wm{s-wTCCQpmq7I<7F^s=ZJBi{f4l2ZCl})a);M`*` zP`ir`9nb((Y25SQFTu0pBG~MZJyU1MfzI5Wi>}j<-VVDiXpf(|-;-$#nWn-Nd+80; zj9+Ugr)6#xP8sR6l1?ae#!muOcN=BZV;#TEXoY-%;*zR-%o6>8<2K z6*ieWOtD(`PWiJ-{-n)=YvtX+&8sHhN9q^bke@%KnIqBTu=Z#KngXJM9^`>aupPVz8Z&v7)QW>M;41hlaLwY9F9-qAAOU26Jn#&7 z5gY_ZK`S@|`oMK?3-D|%`GeUY0W1cqKnbV@4d6KV2z-`Z#ic`4-Nra=*Ai^Ti_!a>4v*jit*4&DxFsHob>#i z%tOD^O5b>h-G5@!BV3c#l*}ww6|67GQ!QS zlx$Fi=Hc16@z|f(`^>cx4 zn~kI3I52^B&;`0dKNtXJFaj*be}08$1WXd%gG`;ZG=Gh)Mj5D3MBbBYQOn}|h=>R& zS+@{Jo05vx=a-b{DAl$pQ4b`SmgEPk!a^&kNtCfkRb09zFF$XVt8vjF1}e_`$heIH&~WpbQj)LXZb?K@P|U89)yfgH(_VG#~-Qffx`8 z!a*1a0V)sxynrLPov4#WKtDJSOo>&f9S$l%Hi!eh;MM{tfmW~&6azibfCLZ&LVyG; z3Fs|w4YY$sPzm%P4BSSq4S+V#0E&SIgn%UGEapAH-;Jur$qBT5nXIxo7u|&m-4^JZ zw;%DNpi}ro@F3hES4Z%vDFb#|G%g(>4ZAd(hwM_F<+XtI4{C@riUl}7j2 z0yQuI@epfTSh+}y;8WE0I;2}(iHpY0jvAYXcp0#D4(TwVjo{u@HdPPo-Q(LXNdvfZ z)i9q)WqX+P>DNrM02Lk=r-Dk*2Bv?*q+HMdx`D%WCM^dIpbM~XnG^=H!5;7jU;&Y4 zhTB}w1HS_ZdqO8+fdR+Ml3#13=}vq7DAiX4NAanmyMQ~2_DJsHk%3_^wIdgDYl`TL zAxSD!iAqJK#;Q_pRUv6pX;oC(ttwqs6_PfU5n094Vojn> z4o}tX3HA~7bGe(tR^@mk3LQQY%^e?#x~|knZIxQ9OoOCaJq}6ju7{*D$YJwcPCVP~ zGP~_ERr9!;w(mI&Y$SO;NxeoMZez$xUMZczh_w_twzWisfhy^`i7#XMeV(ds?^GZs zO>Pld;dNgp)X0_IF27+s-|^*G?&#VJ9qak^h~@r|tNueHX{an~NUPDvM^v1xiX&FP zRuySG{M)K*tKwt~UdcuhkI&=YSWdv*(q7uB8E-0eAm!_!N4Ce|!xkvrWEUr&bfuJA zeda1Y=_GlM*tN}+Zfm=vT;R+X>wnppnin*3AJXkXJ%+N>ps+yRg>#oZ8y~_?{iwjk_CXG(K2ee<@GcD%DjtjHeh#IdYlH#H4(>fl_RN(%a<(*z zN|0W)Rodcy*W`TJe8S4F>>}aAcOnkIxvBVbSU+N|&N}f!9O`k*q7icvP~x`Ra?ySh zSB`0W+$XX4 zeyvmnDD1=#h(h>d%DIn&+=?GW3iRiI0-ZUMbfya)-|<(!N-Ijy&Ac~Xb~M3MuGE71e!|#h zyGYg+B|@DO`Wgn8?*Iz6tE2s{t7TL~E#Olp?tV@yy#WxE3+EqocOrb%Ub%8J4>$hO z87+vlckXdSG5UBuDtqd;N{bxclI4V|x0Ot)+SH#fYo+`8wNk(`x&)NaMl+BRhM(;J z?^C?&|EnpU@!f}cAs2^qJW}}Uc#ZL*j+Z#ToXRU5s(;jq$5Q#MK-!#?Ld3(`%qQ36 ztzJ`HT)I}XsXR}EP2r3kseG@8(*S1W7O^}Fzg`xxC5u18>Wv*){6WSn#vih|0}rf+ z7vjsro?&QJ1l9P3Ye^7v2OF-Dxr z=LK3?c4r^{*Kx72fX|pkFC~nJXiSdgVImlZxeL;1(H%97WTWxJ0$$3h${s{M(vl%* zd4w+{X3Em`2+VUJGa#}3jT8cTFQf#CWmi(~1DM)C?uW$Ec>G5JI>{e00dgv&BV+*N zwQ!v@4YCa~2r?T|1*w7zmZUf-Yz}^vkx(-mvjE6)$Ssh0kk3G7K;DMbL(=zN1Bp%* z!-af)6&lE6lm}GqIqEzvYzrJSt}Vu82={+FQ?5Mwc>fVgChqZCbqm delta 34989 zcmb@v4_s757eBmnSzy&g7F}==5X4nbQBgoaL>C3b1YQ2Ph{_*JZAC1yUH>Esx}a`X zN*nE3SxH!0S&u~}SsDm}mZe!KK50>rjbVl6gOujJ-?b^?drqJ79nm$UO+=oB)T zMAF4%s<1bnzD>rCeeNvqG{EEd%5EyocaTDnKXTcE`Ih+#Mb84j+JRGu_jx)%=-)di z0m*zpp$Nr0nI;J#q^SBK;blRX`#tq`9k2SOv{GnDf+N9 z{P?qvzytuW;&{Il99+x0W{c;Pym^%ZwUfEl zDP5iM;81&lK3XK@wVq|IkhqwspWt$YbF5=(uvy7z7wDW_c%4`D;1JIPWUt!dIkR#b zGNK1>vQ(`iqBk$>5HuFgzn2JN9Ovf!G&E7uKFD(X_t(V{9JgYPXGBNoB!#_LAGR!u z9&*?DjICJXVLPhye9!${qQa%ILVd*LSY<8!&E2L@M*gi(*Hv=H>>hj`*lJY=Rp4;TIYXxywF8iI z{!fTVFiJ$gG?*X#P>sRiM3HV5?hY ztJT|nCQgPu%ZEE0j!HgGhARFW$7hJ=`j7r{IGmFso$Y?5Yq*W<86-syE|@eH^|Cy# zB7PAw6ZPSI2I<(zc!hIyd6vC=)8VMF=ndjuAMgb)x;e+=4Pb~KeAQKGJ<}@^^g1K! zfkozU-9kU^5#s$i%0WuoRHjdc$ibY0Nz|=pc!}+DWQHlr%%?EBTE&+)IIZG?!G1v2 z)}X55lP;oG^x*GCB~cjU-W2~T&QghS98;cR?<))nMf&frGvy7314^N+);g$?ml~P( zZq6OAp2m704WeUe^K$2kKjviAi&nMy!z=L$6Vts3v`!S3JFFv3=2`&R>V1HDb291d zB>0i%xsf%uhH~6eX*xciRf_3!}CB{?@daDVo`amWt!)K+E`cB zrpbyG6Gaat-Ul5H6vb%ct-X!rR$l#&*Jb`hZ!Sz!_TiPC$XNwK0jbc&r?>TSCKL3A zCOn*mkxi5pvP?s+K6ZQYKR$YCfpSolP~=6I9}$tel~~8@_^tW?gEm=6sRtG za~Y+xGcTc|yw50xPz#hs_8s)C=)qxW>;Q^w4WaBjeXf^Z$rtuaefZZPUVeIw+j&@+T{jYz;xN?Gej%PKj;yT)zZ;%3@RZ@?O-)y~uD*pS;}tgpYLn ziQE5Zu6m4T@kHJ;Ow}->_!+xJUsU^%@978XK_rxZs~)gm7l?e@($V1hnCe0R&$I~_ zn$IQZwdcL}-(AErya<9eoO2CA$HA}`U7HZIR^@5?#YJu=MIV`lX6}oVbD8?EbmS(` z`5r~&6MEWXXzzg?eAcSVYAwAlxaw$+-hsWZ{pW9>vAvf~l5Lq~7)*tllZ%=F1A+AR3+#9J#9_O zbq;Q_ir;t~hNj~PY>2FsoRg26kd7nVcx>5F!c{b%eE=XO*nO zz4@=)UWNMOzw7Y-p~CMdPjaITb%%bguS-YcyYnf1Eqc)&uWCqUKz!*xq~<(^AEX zIJH|P;xXjZYkM3n0ZqEaOGj$xt6pIwoSyO8T+;KZ!*Q+!$}pEVV!N!%m<2VhR0;}a zaB>rITvR#D(X_tq2j%+$+7`dsQW1Zvj=8whFRpzG02G$^S18*n7T>b{=u)Vq$(CWWD?HmARGj`cc=uN>n{`O zq7DLL9j~8PqU@$1Uiv>1n4`RhLPb0g*||Jb-7hXKZHs^59kR8c7ypxmIjVn95K3e& z)ZI)}EEfJRT&Vv+!$l^cxkJL`pCoKYf^1Decgtf=yG*F$jzlWrl`^GkcPQQbC#Ap9 zxb_cbTxAlScS!v8PZG8|)om)l`k-@jI{!iDR$M8>c`om!=jP97yS876>~g3(TpGon zFO;3!pMbf6Ik>I~^OQT8I-ol3@P)EE!!#xL>b20Gnsd5%Tdi{4ADo;#a{>3<94Grn z@xocr{639V6j^EM z?EEWqWPd+wvF_`?N;?XEzxcEoMd|hpVZdVnuhO&qBZMO_QnjDXXA$-R;uE~!4uMlI z)A4?>B!MpX`;QR#3SH_SEUem1xB5RTpRphuRGMd?Q@-pblteV(DRG?T^!E^sfnNLyL;tXXP3$WAhp+R)>kPP9oP4v4VA-=~d;XQwt02e$( zuS|nusFI2QQbh-b=-k~gBhef+gaisZHqiMYsRF5@`$NVG`@g3wHy>RqMVazPL6E9&FJu%uq zim1mJ-;gs|oF8>;lXVa}q$&VIF4-80OuZgST-YP>4AIu`3{Y&B!(~G|8?%hLZlJ%#`SfTi zMmK`k#d6wv;s_ylJB^$8l<~P zCO;w!E~kN0f`zxY(kWA-{F9a_6zdvPpj4lW>CQb)P8Q2NYzf^qWyFBL3T`8yjO(pD zcq=v7HaggM1@zk~{e&~m(9S8Ngt1T3p$UG%V+AxRp>uzNHlXVozq^_ZRl191j;uC1xGxS1InDFb^$}ei z9~)nXt{CwTY&S}cn=FITLedqk-)nHARn{pnt4IEQ|IFLWM< zesC{z8;8DpFZ39PK6w|k#M#_`0A6($ScZmk=mYmci#Rm(Ug%y99d|FZl|u*q9V%;} z_hnIIyGK7sogutVsoxB}P)=$5jD>>xe7bi=h%dp?`!8B~NHJwIlKW-l%L5*JW5thR zk|r;A^1(sJW{B#53e zdJorjAP~A%&y7Qp#>i-{Og5snDM{~%!M7&`ZA#LJpXFY9awXNIWeB<->B6*uuwNU~ zqK8~dlx>Ed+lhtk6wZ1PZv147zjvD2LnavmBI@v zXy1%s!m<@~QbwE*v4XD67%He%&{s18gu1!(ScX|xGnbCZOzC|S(~v!bB?+Bab(3y} zKHn$j)TKA(S=}7296|Kvzgg)l?Ka|t+?5YBv13K_k*vXf z-$O@Z;fG@3LudE{nLBvU51v`{tt@ZBZ38`)l_>nUgnG{Q6Ta9=!)B*xr)-g>3{}&| z^RS5|rL)mn=+@cMp$4>SWPia9n0Z*dB1J#Jl*X1~C*aIy>XXyOBW5GLGP{4Dc|cBM za}l(Hs}l*2YXc3)?l07q(U|O&ekpPrYQ$^Hx4@|qEr=1rrkU8APtp_FLBi=w`fK(c zZ^d=q;-MT_s$d9OuPK|pHYdPKg%aj6PZmG{VbizK<~c9;*C7HAMUzy;11VG62E_ig zCPqxChDqO3NS~TJUr70Z{%7vQ;8VOOMsraSW(f99<_UlBcK(17Fi(JGVRJI*ta<6l zvt{shfFU_id5Bj-uhnVYbuq~1c|d|E2PBXRGqU|~wrvgmh1601$8zs<|+vpS9I zVjWyN*h5Ucw|}6sawhg!DYx+|%!CuWXF7d3XQclYfNh^T((U{7VW`6LZX?vD(cf}L z`R?V-c9-_MUAi)jj?0~_s+FnMFQ)5qwWv^L*Y2yK;Vck+@Wv*g+Zei2{G z)Zu#u&Yw&_zh6gJ&DX2@rF0WlZlbTwj}q`|neU?x?~GSe@mM1}nMsBFM`MibT_%3nmTPaoOQ0a5Luv2}2qVNzPV5&flr! zaSS!Gkejq{!GK6BKfi!?7DNy-j_4o=15_%|eAX-}M7FX%z>U3e zmz8w|AO_f;WuL&qDNwQtG;Pu7iGMOI{uI42O;oXwL1@aNpBHP<=fhC%f$xWChY`El z{Fq|>Jb<B z+FfXINQ)+|?Pq1|pH@AJ?_q2DDafD2LVLJQn zIz40#C3*CsdE|haI)?*9_~0oK()VY9u*DFPS!Z=+ed(CRlifQ(!pL&z>cs=yZz9d! zoI$G=4=Gs<1K5rEFw(X)u&q7BL`|E!=-&2IMWTjFMbAF@-r>NxW01n?$7dOqKq%j! zn2au;7m##zNM86F6FW0qUR|gYG=(ikB}`4Tri(cjd5UHl*|DT9ESg*}JRk_#h@F)w zsB9nV%g_xznN##dX>29kQZN(UY$+I7(#-KD0MFdcQ)7@4%k*4-nv87p6|Q78wv&#C z4pI5;-TEBPomurKUyjS*EFn)xj;@1FPUyxq>w&}0LwT6k?=m%YhwJ5sCo2R? zXt`sJnpP|s9y5XCJmu6xZ4u6Lf;hEWHU(+sOkTbWDDUA9)oR2vBV-NQy`|0+F=aNi%<>9^>mw1ID+qo}0Q4q%Z zQ*BYDu&0I|C|W=y>i@{c!tw)@J(5ON(ecYdO78gGw#%xFyL|7Di@J3}K$k$ZTzJ{Hn}yb4tu)Fqgq)`H zEDv%=^QdK@VEL17O7l-(UqjKsgvyHt-X?4gOv&5mx%rAdh;V~=+K)8Z zI)r>gAGRh4zVFg^twTJ*Vx9bcosq#_rp&4*H>k(*A;QWZY1HyD37atYAYp&B7s;(N z)OC0xoEZgM@^6_PEoUbZ-~}uO40f{;$^GGI*&qJC`t{|Th_Dv~SB?{Q{z)HNsT;Pa zS*|S~mPezunMGpk%nix1HyzDuPblQ`{zCQsl^TIerFD<>Ct>vbW2x>Ds0;Da@YS*X zc1FqUcf0DjL8eW)8n%J1UmYWO{fi!2?JIouBW+$iU!ZT&*y2$nm@X+^CG7o%UM!v` z2#aXKnj?bmMXFl6Oi15Hi`R}HafWM+HH>cuQol@NlM%v#w}h#iWy_mIRV!y0j!0v;9O#(?Cl&ucXBZZ&MO%J)%cR8s|&PUo4ZpQ~I!w ze31@bH;p_)A71B8Y_xpcK%w+v_1<-F5b`!P*~&adjF8*rPAhwb{$v{}?A$~9l)c*f z^Ql;)iF=I|sqe5KU!lj#(tX#xj3w}2SnNe3%Tu%s&<3)P;Z}a!qKrL;1@so(Rvt$l zrKihl(Hz|nF4SD4M>ju2HI=m0O5fT=}dhXpPv8kxYiC;gGejK8^i{_T4m+{8c@9)2o74 z`|AdUeQjvWTD{dBW2o6zee?0@f}nYwPOJEez*l=>7*Wvso=6gyl0NlBLO-qRWW}W* z$g-oc#iD`PNNFm;2P1c3d z$vf^N(A_(X!ZnxbZ+Cn_gl3oOcb?rrgjyFmW9J58mrM1To%KZ6D3%Xgz2^mDq`$qUBjc)7ug@byMHlWHTB7pA(fxa;MeTM~FI-*t zNEv_&XbSco6>`ar7TNba8N043l|4 z{fMIx^&;K;hDQl!9AW}H=OeUopTy?7B;fmh5x||6BhdT1DnfKJBmb@UXsfH|btPO7 z-6J42M|{P3`5PIh{J#>z5t0f2a75asu_XUxQ|Pmj8^6 zEtTHvGlGw#QwGKQKH`K!TqfYWL26*PKhKXu71n=5i109gP+&0M|_XexZOCa-EITMmaSPsaiRekJM14sum#8 zgC4R)6l4_Z6=oA8kM3-gRLSo`m&jdDT=SZ z~~xVdby!Yce;f9VQv?s5cp(iW%OJz1f!jNs?qmsL3W#%+kyP*XnEYkaO4*K_U+G#-AWz0cS(mri#>SZ0HKW_Y>rm&2-dSUVk76>Atw-*`J!I5wBwd^?zYMFXpKf;gAPRQvTmaLAw#Q`L47 zQERxg9}C>JuvyWRc>ae&^r7lJ;iX)9vU)B#PKUoUS(r74KK#yu!Uy@Z`JE}k@_ZWb z?tsCOIZ$GyJ5bY}q+~;ov+w6QxLG+}a`Vce`R@)HbZH)-R#mKAZ1rO2cz%Y`zKNp) znH`%)UwzkKIFU!2-i;8>eMoP<8!Xi4(V+K+L9keXUxohaZ7kCTg>8IwB44K7byl zwmNWI%c_cS#9sH@UW)^q0Jd{J44B-M+$#GsjB8yjRBoFZ4H_(JPAsvN)qq01iEX~0 z-gs}2@bCL+(1AgHf>HZ!ZcD@HtOLu1A)fTp1OCFET-tVEKo31OG1*4eD}?r`87lNy zK;vps+@m>HXXn!`HGYE+q6Ew zeHKdLhH6$=9uS7=7Vn>0A%~(_7O@5rpxD&ud)QfY=dZ3!EHi)-TCbv;v z$rp_67>PI@KWIjtC*HLBPfyeswC6R(8WoKnf)|Ja$K z3L5)lqVNi-Pw_~z;nZPF4px_F$#S|RJvV`9TPPi%psoig@gIz0qQvDFO<)t0UwMZ zpHkxoA+vcknW1woj^GK>h=I$L9pH7tposjZRG53*=&Cf9rxkT z9!?GAdZ~jh{_vrm=jT8Y*mKm)q2GPztNHS&$%}^2pI<{jD?RjVjX`!PJ`Sd7s z!qVqZnO_s@?c#~b+4AxFMvY~>!m?D$DR6nNVDk6#5Z70RXx=vU4SDabf z#lX6YZWRgP%F>{}MAV;kGcWgeeSy~8%%$}#7tm)8yY;-?+R`O9e`A3E;mPP(_L~~3JiNR%a9RiMuQ*5nVj)fTZgbPXHlOFx}{+NnN0uHFv6oDy_+CA zkxnl)1jbx|B;`5r80j#zHZh`|mvww%8UUp?CtvWikk37xKip>Z_j4V*+#<&*J zwxfOl&muC989?P%9uE21v?lgbEGn{+G&-np+&Jf)_sKHZe)6I`0ko>tp;m}tkoHi)7;C&3)Ewk}c zhG*~Rw6QTn0OoIv`YDkdWzgr3yKQo}H4;v)iEwh8y2u$6xSu~9NIEf%ha|Om*K}8 z`tmPP0T>*4ODobUB*O7Lp5!v<^G#D-Y`@C9{U-DF_Fuo_?zDdUsW0fG$3g|Xo<9~o znAZjMGQ2k9*@kB)p51u%;duv7(--vWv1F~2r4|4fo=!aKFX@cqnFuIU9oGxzQt9#I zQv_2c?ftRui1}%JFyS-IJzkH?@cBxGEnkIcYJ@}RTrU}7j>?oJ{?X)aq?sQNAtiM6 z$Du*IT|YvWG|2gDvtnOwH7n|Djw&-AsGNQK4 zkJTm7?@mqaA)*-C{*fd)`t!hm9gvZUJ&A>poeg{A!zQ7)K*+@kOHQIoKTj97g;dvl z{)-^!rqKOg`oXxJ_;RB9;nk>M>vUL*l`Yigt3aOw0160>;$wLUl%2)j#75ESUj>wi zPzL|hblHtib(~Li7MlQdkj>pNAp$qz;mK*t(R?^=P2rvHG7*R#$hz)Qe7D%SiGcFG zSJizD1gN^YEssH}m;ecM(m}m1YPK4sR-NghT+kzBq=xwUJi_ibF zi+;SVXhvdaXqR~YKp6I+0hPJ>&5$xWKrGL*Q|hg-r*obF2|ycMw%;Sj4DS^y1} z!I#4dUej9c@GSob?Zm_tZo%>nGqI?FDB`Ejr{ROLqhnFFro~!#$LT2oDBJGVmdESb zP?zm;B3aB%-=yu4@(wFWGG!Dfyt^GJCkHr_F>%u}>bro^nW*H%hd;gI%o&<_#)wAd;# zw=kSFMQM-}J0V-vF`O3sU?}<04EE7Mt53yLO>EOL102_z>~I&@DV62GT!Mw0p z$gbj)xCiTkoZSuIbeUM^FkT?jO;lw&ml4;x4ik>xf>I20fdhDXdFHI44WzZ)t`B44O z{q8AD{&~1CVg$ARJX9DlobLKLJZ1-<3^;0DhgE$X!wog}e;w7cn7bnN1uFIoec{(se*=&d7GE=eGwphm z!SwY6L5H`2y8jkf^6g`Y$r$kEOU*od4%MX8FW_HAJpeUei}T0wQ)FBG%sjz9gp_%0 zHO>|UY|gwnG@=%g)|orG#71E>(C`i;@VG}D@%5CLfO&jpTy_+S${sKq>Bkc_FJDjDH299#PR8k5*!>1|&__3eo&&LbFaq>r@g zdb}|MY}B(^L+MlPX%m+X09EJ{l^2i7n6X_ou@*RBCYCCvqvhWq2-d`&JIvv~4T6gw zdjo!BLjWCkC0wu$p&3_(3t>UD^vbg_S|D|4Oy<9{EDWA7!u z4|ktAgd2&A)zAOlEC|B~(iI((g`a}x2OY~*4VYXRCRRsduIG?_RJy)c*cC{H&I_$30YFYH+B)VPU{LSRJ9FivMV6zh~gQR;vr83 zizi>qr})BjMG!Qnp07yRD4W2wQM|%jkMXll9UA6AO&lIK5uUkp5O60V-)nFX+XGNX zBJRbzx|>+}o6_5TNrVuUCH>Twl=hg-`CR4$kFrQh3dvgOf|g8HDmh?~H!0{*%F9!{ zk$u{m4AG2z1I>1Y(&lpL32$=H-GzsM1Adb#e8_mO-y3m&UJz#P?+g_X6z@cq_1=&s_(Yj1+O^^Y^$UI zUxKUC=cTc}WT5BNE(FVb)Ed7^TI5RtL&|ZE4t3HN!#ul-hoV^M&iFf4=-9QD(mr1@ z)+-(g1ZvrA;4J;70ZYI8k{QF^+Usz%=_-;`MvlChFUf49W4SJaNhs----jH3Nq-U} z%-Sox(x1c%-|mrq=uhSdtM*Eh{79Hk_v(SAe#DOmKFg)Y{mDxAVs0tk|48Z)K!S8Z z7~G1~FWESJ^k|+34k{AAG_uvTQhWeO7oOR3V0!==LWGICr9%VABdXdDoij!n8%VCt z+yzQv)Fw<>#~H|YVC7B#xS{I@Wx)#_XB?+cpb|?v34%)@hYe`X)NPuqy-e(*Z=B}Z?PTTpPwUYCto)Uxt4@V z??%|d5gK#rZ+FWF-P+ADV>zbdl+A;8*ip&5%Ddg$=a)~K_w6DBJEgS$gEJ^ z+1)j;6cy}K6=oxN07D?JK@a$PVeWDQ(#vwjSe1~OMOqh3e0|PfZzZ;4^>kRqLw2%A zqIOC9gNa|sE-sB3N(Z(j_@Kt)HFP$j10;3=p2uYiimU|Elm~*Fs{65Yc)WzKh+4iP zPPv0T4;6csb%H@LNe|h$8(HnE95E@(nS0xri*)98J986CoY|+HS$x^dD{gY;5}dim zoVjFYuF#pA7sp3}BhTdk2;u|o0dhHuYt3*%`lAoK(Fe%WbDe{ag~dIKjpWGP(nMre zQ3A=W=QRPu;GuFMDi6wH4-N(}Hck$)Yu7oN5n{KfZIcvMP_n(*1&nfrm!p*JcvNUQ&sb zPy*w}YcA*?53|eB40;nLp50-`_idScSq5Yf)GONr* z&dc=VmHYdjyqxn@#ewVxz4At$_7H zSm!wO(>a?X@0!g|42BBbCB24M55}jZ))k8Pv%zFg*hht6b_BBZ>@s`+(NK)W1jngM z?|>=HV%1EbA5-!!?v(xPh^5#t_GC~~sr z9zUXX2K`{M6bWnLyx)MUXd&i=| z?CglslkKx^0;UZmGdyl0!0m|KZ(<23lpYQx{zINcsvh)y2;q|wi9mF{>pTGLM;wn; ze!AcCv=`|wykn94y@+nWW^^AD#;r!T91_4E0I6rIx4S z+vZxy@$G8CRu^PDf-g{aVHp?yTyQHF7~#O^nT1Oj&a(;WfItQ<+5%wlXZ+j3dba-- z?wiK({R%%Uzp{i6FQ>uJcn6xeu}J%YxV4Dh2%&{l(9Q^Wzy?ohFS9fxOnu zP%BEoep^plV-RfPUdiA>bXk8uGec*uOLmsRb4yh7Q$`?Qg>^Y{kgeR8*t%tbaWZ+` zx_q^x#NimuW39GYe1UR?s~UVaF4x^B{mX?6)b05jOs03@gn5fzD)A!OQi~Uf>hs5T zOywE)h(+acGD02AE^U`W`j9EY0rfIO`UCUR>g$!{eZwqe89hDu?A(Z z7e`7{l*FVQ4ARo`N)oMn1s<++PDvIhP3W-{?@Cq&_&kTD)?tlep8?IOIU;I}{2v?E zAf0n1q3(0w{$(FzlFE$)kQQl(8ySpOiW{jA9*R8hwHxV+>y3T~+EpZy2)kEGLwXXk zkn@1Fr6(!t&DV{+ycI1QS;k$;0z9o-a@)54r8KrgFce8Ae8UE&0XakWbUQ6z1^*Glr4P#7#XE zv(qlM3@0J(8l+9^tkgS<_`2)l%mHa6&*#ks%6 z2Qf%Y)MDVI{b3~7-N-fW=a;2(z*9SQ>q%L+K0Sg&mE2aNpMWsV`*>bd?(Z<*(g!Xi zuwZ=ck)55?wv`7yTHDNZ7lndo_Bb4ZY*E(1c4cq5l1pQZ&N9us%M+_fzKFnDraI@C zTx{*@h;(BfPk@?J;rY9@`H4yow>#Pdn!OGz3D?`C&Jkp=5ELT?jwG`^$Kbs6ec5lB zqGAcNqzxm`$p>rYkiXho#KjWG5X9EEV3BrK$`=f#7FhypC4~x0KXHW_vsHzV?P}~c z;0v;GK(2=qHm5iGB|Bj&%yw&QY?OQpVJsZa{!pB^{jpn4f6T;=*mlCQJku0`E2MYoL`8kILMCp zbS`^uwJZg#c?*|9e;kt7Qd=C%?}GG9Bw0A7s}Ejck~z-V3nP00Q$O3DYtF!*Sc0l{ zob5;|5^%Q-Q>nxCgcKe{`o|wbW8xH5)d~5nt~!NxL@o9ewocbInnhyD6wM;LI`Kn* z4Q)&=i6a=*R5gNl(vN}Q1315^bZ(4TbvHIT4C)|@E0>dCfQA{y4_OLSTc}wN?Bvc zpv18t;CSyt^oo5ko6lcy!#l{}L(G0LI%{A2?Wj8lOJxMdd;2-|UuCx|UX?x?OM*&1 z2SnV!y~>YD@iV;1$PUY(Q(d|Ja+O--*vm-5RjfGtC32#BT=Y6PxBX&v@V2dx`V@B;1HXIY>pI@7jYBUW~Sn6n{N1I4!1RF z9H}a6lZi#}tbAKbR#zD&{J9%x>o_uU*6HMqwvwma8SQjsOtwiav2pH*^jQDN7D>iI6O-N+hIgYW7t zp)2x&sz@pni>~;1ncjI?QWl zi4(Cg>}y-ABo>b>#}`>XYWM2*w;}oA5Q~&L7@Nfc-^1qG=xG5D)BK?MTya{<_!y~DPl-Y?HU{T_X{GkFJ z%TR-De4lp1>dF2*EA5{|f+xNZJUluzJ<(17E&hj-5R0Tin>}8+WhE3}MUevwy z<=33}IsLciB#nXSA~|oii3+}mgRxe*Go>o#--l`4mIAx=acMQXBWLP+3au$*u=cB`CRnrd(@ZG;#4vkF70!v#MDEE5u59m z(x0hhQZIgErTFzpO#*nfp}<()Hs7Y zL?%d4Gl?E{f6h!2IMnhnl&W(MW5=FVUR#{)ys`IantUM-Y+ekkm{8Foy)=^~#2snk z%ZM)(_A!#SAlw+mUykcu2C1qH94&rg$||1gyi@aNhJ1fUyn=l|i!{hcrj<;%Lm~l5 zyH2KnTfp61@OyT`(%+x}@} zI2kG>r;(A~T*?&*(dw=(Ems%|;D@9U{QzDB1}YK=FYQul2oZDI7n-C`(@0ETj>Ch3 zTnE4l!?*4&l5aX0PXeUObTXtj-zIk?L7)1;X6=(UrIQeh+x~Pi`mXW+Ii17-8k#{u zgclm6vI(kWxwLb)3yS>Qh^H_G==>+tVDlGPL|Y}B%tJI zg^X-s>tA#@3}|4&@@NyYB4hhC)}^t)<$Zn$#GHUuh985vdF1wWZwRFTl(I4;H|P;9~ZRZNRu z50AZ$Z;-#L#h-}e|GKti5eHgLWD5}@Ka!TuCM#6@=-=vYu95yTn+(-Fei(5yAKb=r z-iy8@jm##)OJ;ItaJF3~UTLf2SEih|-)HkV5&`-Jz1hx-;8fl(;Am)u5+AFLsXf{eiP{2qVIG2c^1s2*({bD0$@&9sc}{G(3k4^vOKfZ8_V%7T0L- zw?_Ii!$Il(91HV2Z(;md~9|_H}MqLHMj+#m2W>}W36XD zp6Vz)PBx_o%D%Z?f&nN9s?UH3N`ZP~^dNB#@QIy18)+X0>scA7;Mna|W_`|ls zt$ot&0X?UFBuH04t`25kZ$6l903rS?(g4a0+R~-FrUxkz&E+oDQ zHJq`&pvavl`7XRKP+=0;EgTs+tt9IGw_AYiK)@})Gp|V}3K4qX7rK3wZP;?sZ@%d# z1uZ2Wo{!$9!B!(ly}tG7N%w($Yy()7G;b;5fWu#tRxBlf!s$KIj-@0W6RK?~4poa^ zm4-Y7PpC!8e~A1`*t%EpdYDZ2`3Xm5*=?=}j^aYea-Cy2!h4-BOUoW6q2oV$+1YQ) zNCY69>06dye7A!%%%O>!Zwv@~1$nFjKKEVRL9B*JUp`E--OCatD-M?>NOOvaUoY%9 zYBqDgW*KnUy&00?f!e@F$eRJOnNLeIvAHl6`~=OjED82TG|j72tdrUvAuEPl!!#4) zI{EMCE`P+HU87%eTrIAhXIl`1JH>HwaX_cEX&L#~z?ECzs21~|QvOqhpF6IE=mCJ4LFP^)ay?#=o_&-I^MB}h@Zr3tW96R|U78Pe4s*JdE2Wl4Noevj zReU^spia9(kpFo|Hhyhy9_EBA`A?hAVa`S+|7q)am@`tzf0`0oK@Z<|cs(Z>Eu_DC zBKAlziLHFkw^LefA>%c?L-y43_@i9B%ihBf`dPK(@7bMl7K=xhhK`2qmR4BFMEU%Z-}vvc58QVduv_}rN@9l@L1V2iQ%9lnhC%z>M*FcgL7B}*^TUo93=K|%_EOz!QE=PQ= z6vwaMU}yLV(2>e$n`~l{s30~^DV-RXZ5draGT5uY2Ch3S{S1B|HUE1qQEvD>yM;V{ zi7aGWlhWn)QtZUucgXZuYr=384Cb^Iwh)}wsS%~&GLERt#s;O{5ycr`hZ8u~1nKH> zl1Dz1(pQjHa!DGu5}~q2Y0gS=-*6t?frcwMgh0IP^X!7$Oc|R3c5mfsgL^!c{KAnv zDn&ZEk|dIUOWvz+#f4ucvPVTq@vDe8;)YqP$iRVnQHAr+Ht3Fa>{%epuHpqaw%IE^ zvx>|j3h6gslV>Ea$4J6}XKCwj!p4=sU^%$8h z1+FF!D2E+^Ca659m7ZNqrVU(M$3+N<^?5u|RUm9iytygoug1h%SmoYq7v?$*{9sT| zlcPvmk;shfvNXDwM8okfC?<`rx5hwGOBKarkTiP@DJ3T9+!{=}*Pf9&*O0NovS$v2 zuSL+A#7T!r;Dp|H;Kvf|s)Q9!OT*WZ7-?`B8H$fs(PxuIRnU{YkDg?+mMi>x3;-YY zJ(AfSt{Q1s8QCJ-h>?`#Bym6>)(!svlYbUq%9_PL>o-SNV8TJExy_OmmE%b9{t?m> z<+!M0sF3Q*$$Gs3>q#b8J@;7rhTg?2xNwL5s z&%UN5HjYQu*JO#;5g@-44^I$re-e>&MDTtO2R^@^;o?9%)S)d7mC;0HR|K3#VPpv6 z$SYRU{etsSC9k>t8^5e|^yw91D)vfbbM*izzY6}9e?PnUNz!j3gS|5D0l#%%&L;8!>DM?4!?NaDOrFX*1om70-d4pT zrLf0w4l)z_1DU}t-~A0~>*GY{x0Ii=!POhi{O>_{j3eA2??@FQ={J%`60ty|u|WCs zwnx3g7j@)4D_sVlo-m?H%GwNje?(fbnS_!3((cVRQbGlpTH*_ISaRkiztyaV{MIlczqRa- z5xiW-uJHF*_OqM~V&BVeJ^Q!(4rQn1cNqIveuuLo@;j0pl;8gBZTTI|UX$Mw*h_fZ z8Vrt-5tPLVjnmhvoNd_MrTp$MWQNKFgBd3)oEgZDv#D zcOjc3zl+#7`E6mNevRzJY z;mIH68GeL1uaB$fNAD-Uqf;=QcmaA}UVLit&v3VSF50SMv@Qrm<${0pA-bqD+|MNo^ zB-9Df#=5FYxnvRL_g|V*keIJeJEuVO$6~SPBw-<#5C3K7AwuSW5lx&o>NcUd%8)?KAGEN)K zpfrA&8>FJGI65dg@X=Nrs1l7dh>}?EKez)bCbm>8uU;^2hK*SS^DL9dF|PrT|m7P*dPNNx`3VlW>=j+4jM>n-p30$ zh3hLh{21Vs{09dLGh+fyZ1u+UnrdXTP|Fd;YvGR?C$ExpPm^)+ydB_$8<{I73VMSb zr|`im68@FEJrpA9%{XPQ?(j*AT<(bCY_n4<-{tOjmQ8~|yGyXn9vB2hO)P&d;!sBREZ@gxS2-(s zmIVM8U+Yhq>j5x6&xzs%Y`wH{2dCk2^mXo(R%?0p2q+B$O(RpgZo$3;00d2;K~nol~H)T<~BEb&Ut%Ib4B7QV@AOw zOl(JZmRb9hH24{~V`eG$8B#-nq<+tmtwLOh^xCr|yLS*a-)+6H;cOAa{g)-L=U_wi z9ELw4rxr`wrGw9r*q$<$yBPWZlz0ANQ61+VKQp+9{8j-$K+u?ozcHYJN^o}piyP35 zQUrsF39)FobyZMeXh0?RfdB@TISKzS-0C6ph&EW|agu8z=hi~zcq5|@8_A?` zjB=JP>vgqlCnqmW#x^zRGRyKGhlUV&84-9*TLihYWir{NlO5zLlJJ}anKKRvDcF!b zub`ZvtzOG|-H|NEl9Lf9@5$omyDYmF5D{h+r2 zPr{k$P!4#VW>g~QwopOS);n5WucqTA=aDtZ#q#L@zG*7Tw@ts%9al>T44a|9(FlE- zYVIU==Wy;o;yiLf=MZsgKl2a1hg8xHm33{?;kL)<3UkGT1Gr(ICgvYt1Puk}7Dz0M_W>9P_ZgRd%Vf>N-1#ZK}=b>=i|H=EPtPfBmb82&E@*b28@ zSij_qgasNCg;eM+n&o#}gkv?E8L$^gsqnm- zCRANB2Wab|sG`z>k*q1_k5RYs;+$@e9WWVCuHk(3fFdBB#Z5pn_f=%L;_t_TLYa6le z5vm;Y!bWlDeKsG@gH1fdCc3Rc#u>?t>brKMSaOIZVN#^#5c`-fG>EjrEFi8G9cFDA z8g{OCz#rbZlhm1cI3o>tKfv$7L7EC{uBK0nfN6G+F3f4pC))wfepaW5PY+`vHB;36 zj`<6pW9-_f4Ct1$PIt=`50A0qO4d!5C3e-b%8}`m>6RsCe#ENBDUoa>l?BMlzPy9d ztFuLQ9XkL6&4;)VW)M}!*-Y`~hq%*QU{^|>wUh#-6glfAD^yC!l}jm9N>L)EPn1%s zlv1daQbeU};(IcL=kHlOAKzkH@q2cj`Dma^OJs)`ePR3 zF!zJ+2k9ZFzE3rh`ZJBR51a+=pKGLrUNLB>`G^|R_CK;yjIYv**fW@-4$=#}-e2J^&(23;5f)q{{A!7Kx|O}dyBCYott^}$ zT`UG#Sz$$JlhUry3N!}P&fjFz8Xdz*G1X9?e> zIPU+PNV6!BDtg-`I~i}DsI%iERT<*`U+{E6h6rq96Zp|Y@q8QmEkCOhSKILBL#a;q zoMY82R+!JR5Vlm@JjV_`*GA`=i1o}&BM&UnqF;_@xAn^K!}W}cvT^!-@;Qb!aq>J{ z$l6T&0{ezJug%0)b10|VvQqrBotdMV7*wW5tb&m{yMx zV=uAL(X{iY2KW!1bXEGN>8dD^bP0o%<6`?I_5$yS5$7+l_%PC%ucBA1a-1!5aq2rL zr!?oJ(_4j;BLn3o3$XnBq5N&vSyE%fq7D`?s|aVARI76K^cc0{{V275 zIUexZc^QX5w?>@4%vSR48q>rp>=0Y@{>;H4tY+s_wxb2tBqeV(;WMn&qVF6WGFQgp zU7{)12IXmrvc%gxxi)2OXNj%@YEwzg7mJ?vNW!y|1-ddy$fJbLt0J8V#ET@&J?V?Bd!j8Z(G|hbDcR1oL^ps)1KBzK6m}(6JIQJn@}ym{yp%nb{82C1HRheKmsLHLipNk92GSfa7g5KB%wj z7<3vkKO!x)@a$q<`L*bFESTA29PWNJK_yh@411nJp4B?o3}R=fZq`73m^p0MQle{u z-NQ?Ez1D|_xrI!dVTu*!dLoAPQBGZ0K01wb`bozKo#Aev>K>!4_C#d8DVK~h!ds{e zy$L;H{;6!IGZL+iOYa6`8t&m&SzasGtq*C%ZvFBnt*~1xFQIMOKN6>z;X9r3E_~88 z75SDen+J!g$yRT1g!@$7tfJN3=%3wuLK{7fUk?uL-OgXlH!tH-3+Mpd;CsN6xa0+b z!LvXIGQbY72N*#eXawg$7qEaq;Qlk%fmuKclEEfW4r+iIG=Ynt`)52~dVmebWG;;d zAs`%RK?2AC+2Aek9ykFmg6qHn9stMXT=D_WfN-D%E5Le?2TH+ya16A7PS6hqfqP0m zmnNsc5U7D3e+6Yd9dSC<)zbQ z(SZ1Om&HH4`92?dvzA`D?Q+*hW~AT4UPEvEIKE9(`tWR1#W-H)qpMwj@<0VB0(rmy zGC&&8gIGXyEBc96$^t1M0tA34wRDudn6s^sd^01K&GJzh%f>7WI`kzN3 zpdOTiET9K7fGfC-m1bIj88m=8Pz7><0c3zA5CMEa|9t2JBgh6R^L^18*zg3m(K=>O z1x~8)+&4cy#}mK%0k&h&Dr?fwS~!$!feu_R#DhVUs1D^pY=k%!%Kg1l?6l~@EK}C_ zdnh00S7?_-4k{2g%Gnd=@Sr*N*;G#M1~i1737*f9x)JXmHrq&M_9|r7Z$PzhEZG8? zg(9v7N@=HHh9mvv96olMeRatqBwH&L+F8>sR3KgzBPKkHL&rXk^z)$KW~Wd4)rGhP zL|H3OI^>4}e&UBns)4;7rCn{5q+6d#Qu$;i1xGSTUB;xBzG6}ls0W>2u>{HK7LyXd zanKJ!a8LCm@DZ>8-#bit5#)kea1;35Wl}sS0A^qT4)>V2u#S6s=)clPlT>^CsD|aS z+T9bqg*uFTy0_slpuOpYd=M*Eh4FdgV(~quJt(lV@r;vgn!+L}%E&K=HvdYd)7$SU_)WsOxGgBhuASUs>C$rLPBHImdqRH6RIYQDD> zwO~jpoTN={h8R7M2f693NwnXYl;l5(G*pP1WsSMTRwuiy@;6pl4N2u4fh6bMkhWgx zR-Aj@d7R`bZqDOVVv-Bguu!Cw7QIH5CCW8CD;9abi6Uh-(h!jd~&hBauQv#(s*~O_f z=uoJ)I;~oyw1$ToO18#-u*i0}drlei_P_3h(=N5FNAq2!xU!=PWazZwLMHbXGa|XG zcPLV+N(2=}RR|V|k$l{20}3Gn3N}eimWy&qL)X9|yoy(m(y6w^}O1k_#3XSHz z4!4`sVtOKi(VAPqQ&m{JjlWApK{TD zF86;#-wi6ZH=?+=%N-Yu#Bf=FAQ$7l1=k7`A|SQyB07ru_yl=qq!6H%bCeH9+|2+X(~Vv3s8^f&k#AS zBuHIKeWWbBNlb2YAs^s0Nr6uG6sXHc(iCB~ub39iC%Av;uNiL2Mt||f^L)JfhQP;Z zuLsJz;}RaEks<(sT)1N)B1J($M^3sYDz&BDx{1O)nvdr@Bjf^jb(E~bH>j2PjTl9~ zqZ3D==lD&kM*22YN%Kh)e}g}du9c7d`L5K6**Fwcd8lbm9RKBrz2&@VpN{7`Bz>z9OLTl{AgyspVb%go^2=*7RxQ?&Z z(93A{;eQ<$>oWOMGwFW2E#%I@_B;&Gp2JuG>GTR3?HfsY>(5hsk;%hMeVIIh+%WY8ah0RZR*9iR;~fd)_y>VOfHf&zfWrG^hX>Z)1T ss|S$g-TyuL)<9j)=$;iB4offsData1 !=0) // åñëè äàííûå â Data1 î âîäå åñòü, òî èõ íàäî êîíâåðòèðîâàòü + if(LiqOffsData->offsData1 != 0) // åñëè äàííûå â Data1 î âîäå åñòü, òî èõ íàäî êîíâåðòèðîâàòü { // ïåðåõîäèì ïî ñìåùåíèþ èç offsData1 ÎÒ ÍÀ×ÀËÀ êóñêà mf.seek(base_pos + LiqOffsData->offsData1); - mf.read(LiqChunkData1,24); // ñ÷èòûâàåì ñàìè äàííûå â ñòðóêòóðó òèïà MH2O_Data1 + mf.read(LiqChunkData1, 24); // ñ÷èòûâàåì ñàìè äàííûå â ñòðóêòóðó òèïà MH2O_Data1 // çàíîñèì äàííûå ôëàãà äëÿ êóñêà - if(LiqChunkData1->flags & 4 || LiqChunkData1->flags & 8) - MapLiqFlag[chunk_num] |= 1; - if(LiqChunkData1->flags & 16) - MapLiqFlag[chunk_num] |= 2; + if(LiqType[LiqChunkData1->LiquidTypeId] == 0xffff) + printf("\nCan't find Liquid type for map %s\nchunk %d\n", filename, chunk_num); + else if(LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_WATER || LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_OCEAN) + MapLiqFlag[chunk_num] |= 1; // water/ocean + else if(LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_MAGMA || LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_SLIME) + MapLiqFlag[chunk_num] |= 2; // magma/slime // ïðåäâàðèòåëüíî çàïîëíÿåì âåñü êóñîê äàííûìè - íåò âîäû - for(int j=0;j<81;++j) + for(int j = 0; j < 81; ++j) { ChunkLiqHeight[j] = -999999; // no liquid/water } // òåïåðü âû÷èñëÿåì òå ÷òî ñ âîäîé è ïåðåçàïèñûâàåì èõ â êóñêå - for(int b=0; b <= LiqChunkData1->height; ++b) + for(int b = 0; b <= LiqChunkData1->height; ++b) { - for(int c=LiqChunkData1->xOffset; c <= (LiqChunkData1->xOffset+LiqChunkData1->width); ++c) + for(int c = LiqChunkData1->xOffset; c <= (LiqChunkData1->xOffset + LiqChunkData1->width); ++c) { - int n = (9*(LiqChunkData1->yOffset + b))+c; + int n = (9 * (LiqChunkData1->yOffset + b)) + c; ChunkLiqHeight[n] = LiqChunkData1->heightLevel1; } } @@ -118,22 +129,22 @@ bool LoadADT(char* filename) } else // åñëè äàííûõ â Data1 íåò, òî íàäî çàïîëíèòü âåñü êóñîê, íî äàííûìè - íåò âîäû { - for(int j=0; j<81; ++j) + for(int j = 0; j < 81; ++j) ChunkLiqHeight[j] = -999999; // no liquid/water } - if(!(chunk_num%16)) - m = 1024*(chunk_num/16); // ñìåùåíèå ïî ðÿäàì êóñêîâ ñ ïåðåêðûòèåì = 1024 - k = m +(chunk_num%16)*8; // óñòàíàâëèâàåìñÿ íà íà÷àëüíûé èíäåêñ äëÿ çàïîëíåíèÿ ðÿäà + if(!(chunk_num % 16)) + m = 1024 * (chunk_num / 16); // ñìåùåíèå ïî ðÿäàì êóñêîâ ñ ïåðåêðûòèåì = 1024 + k = m + (chunk_num % 16) * 8; // óñòàíàâëèâàåìñÿ íà íà÷àëüíûé èíäåêñ äëÿ çàïîëíåíèÿ ðÿäà // çàíîñèì äàííûå êóñêà â ìàññèâ äëÿ êàðòû, ñ ïåðåêðûòèåì è îáðåçàíèåì êóñêîâ òê äàííûõ 81 // ýòî àíàëîã ñòàðîãî îáðåçàíèÿ ãðàíè÷íûõ ïðàâûõ-áîêîâûõ è íèæíèõ äàííûõ - for(int p=0;p<72;p+=9) // íèæíèå 8 íå çàíîñèì òê îíè äóáëèðóåòñÿ ñëåä êóñêîì + for(int p = 0; p < 72; p += 9) // íèæíèå 8 íå çàíîñèì òê îíè äóáëèðóåòñÿ ñëåä êóñêîì { - for(int s=0; s<8; ++s) // 9 çíà÷åíèå â ñòðîêå íå çàíîñèì òê îíî äóáëèðóåòñÿ ñëåä êóñêîì, à â ïðàâûõ-áîêîâûõ îáðåçàåòñÿ äëÿ 128õ128 + for(int s = 0; s < 8; ++s) // 9 çíà÷åíèå â ñòðîêå íå çàíîñèì òê îíî äóáëèðóåòñÿ ñëåä êóñêîì, à â ïðàâûõ-áîêîâûõ îáðåçàåòñÿ äëÿ 128õ128 { - MapLiqHeight[k] = ChunkLiqHeight[p+s]; + MapLiqHeight[k] = ChunkLiqHeight[p + s]; ++k; } - k=k+120; + k = k + 120; } } delete LiqOffsData; @@ -149,12 +160,12 @@ bool LoadADT(char* filename) //printf("Loading chunks info\n"); // read individual map chunks - for (int j=0; j<16; ++j) + for (int j = 0; j < 16; ++j) { - for (int i=0; i<16; ++i) + for (int i = 0; i < 16; ++i) { - mf.seek((int)mcnk_offsets[j*16+i]); - LoadMapChunk(mf,&(mcells->ch[i][j])); + mf.seek((int)mcnk_offsets[j * 16 + i]); + LoadMapChunk(mf, &(mcells->ch[i][j])); ++chunk_num; } } @@ -164,14 +175,14 @@ bool LoadADT(char* filename) bool isHole(int holes, int i, int j) { - int testi = i/2; - int testj = j/4; - if(testi>3) testi = 3; - if(testj>3) testj = 3; - return (holes & holetab_h[testi] & holetab_v[testj])!=0; + int testi = i / 2; + int testj = j / 4; + if(testi > 3) testi = 3; + if(testj > 3) testj = 3; + return (holes & holetab_h[testi] & holetab_v[testj]) != 0; } -inline void LoadMapChunk(MPQFile & mf, chunk*_chunk) +inline void LoadMapChunk(MPQFile &mf, chunk *_chunk) { float h; uint32 fourcc; @@ -183,68 +194,69 @@ inline void LoadMapChunk(MPQFile & mf, chunk*_chunk) size_t lastpos = mf.getPos() + size; mf.read(&header, 0x80); // what if header size got changed? - _chunk->area_id =header.areaid ; + _chunk->area_id = header.areaid; float xbase = header.xpos; float ybase = header.ypos; float zbase = header.zpos; - zbase = TILESIZE*32-zbase; - xbase = TILESIZE*32-xbase; - if(wmoc.x >xbase)wmoc.x =xbase; - if(wmoc.z >zbase)wmoc.z =zbase; + zbase = TILESIZE * 32 - zbase; + xbase = TILESIZE * 32 - xbase; + if(wmoc.x > xbase) wmoc.x = xbase; + if(wmoc.z > zbase) wmoc.z = zbase; int chunkflags = header.flags; - float zmin=999999999.0f; - float zmax=-999999999.0f; + //printf("LMC: flags %X\n", chunkflags); + float zmin = 999999999.0f; + float zmax = -999999999.0f; // must be there, bl!zz uses some crazy format while (mf.getPos() < lastpos) { - mf.read(&fourcc,4); + mf.read(&fourcc, 4); mf.read(&size, 4); - size_t nextpos = mf.getPos() + size; - if(fourcc==0x4d435654) // MCVT + size_t nextpos = mf.getPos() + size; + if(fourcc == 0x4d435654) // MCVT { - for (int j=0; j<17; ++j) + for (int j = 0; j < 17; ++j) { - for (int i=0; i<((j%2)?8:9); ++i) + for (int i = 0; i < ((j % 2) ? 8 : 9); ++i) { - mf.read(&h,4); - float z=h+ybase; - if (j%2) + mf.read(&h, 4); + float z = h + ybase; + if (j % 2) { - if(isHole(header.holes,i,j)) - _chunk->v8[i][j/2] = -1000; + if(isHole(header.holes, i, j)) + _chunk->v8[i][j / 2] = -1000; else - _chunk->v8[i][j/2] = z; + _chunk->v8[i][j / 2] = z; } else { - if(isHole(header.holes,i,j)) - _chunk->v9[i][j/2] = -1000; + if(isHole(header.holes, i, j)) + _chunk->v9[i][j / 2] = -1000; else - _chunk->v9[i][j/2] = z; + _chunk->v9[i][j / 2] = z; } - if(z>zmax)zmax=z; - //if(z zmax) zmax = z; + //if(z < zmin) zmin = z; } } } - else if(fourcc==0x4d434e52) // MCNR + else if(fourcc == 0x4d434e52) // MCNR { nextpos = mf.getPos() + 0x1C0; // size fix } - else if(fourcc==0x4d434c51 && !MH2O_presence) // íå áóäåì ó÷èòûâàòü åñëè óæå áûëè äàííûå â MH2O, ïåðåñòðàõîâêà :) // MCLQ + else if(fourcc == 0x4d434c51 && !MH2O_presence) // íå áóäåì ó÷èòûâàòü åñëè óæå áûëè äàííûå â MH2O, ïåðåñòðàõîâêà :) // MCLQ { // liquid / water level char fcc1[5]; - mf.read(fcc1,4); + mf.read(fcc1, 4); flipcc(fcc1); - fcc1[4]=0; + fcc1[4] = 0; ChunkLiqHeight = new float[81]; - if (!strcmp(fcc1,"MCSE")) + if (!strcmp(fcc1, "MCSE")) { - for(int j=0;j<81;++j) + for(int j = 0; j < 81; ++j) { ChunkLiqHeight[j] = -999999; // no liquid/water } @@ -253,7 +265,7 @@ inline void LoadMapChunk(MPQFile & mf, chunk*_chunk) { float maxheight; mf.read(&maxheight, 4); - for(int j=0;j<81;++j) + for(int j = 0; j < 81; ++j) { mf.read(&h, 4); mf.read(&h, 4); @@ -264,23 +276,23 @@ inline void LoadMapChunk(MPQFile & mf, chunk*_chunk) } if(chunkflags & 4 || chunkflags & 8) - MapLiqFlag[chunk_num] |= 1; + MapLiqFlag[chunk_num] |= 1; // water if(chunkflags & 16) - MapLiqFlag[chunk_num] |= 2; + MapLiqFlag[chunk_num] |= 2; // magma/slime } // çàïîëíåì òàê æå êàê â MH2O - if(!(chunk_num%16)) - m = 1024*(chunk_num/16); - k = m +(chunk_num%16)*8; + if(!(chunk_num % 16)) + m = 1024 * (chunk_num / 16); + k = m +(chunk_num % 16) * 8; - for(int p=0;p<72;p+=9) + for(int p = 0; p < 72; p += 9) { - for(int s=0; s<8; ++s) + for(int s = 0; s < 8; ++s) { - MapLiqHeight[k] = ChunkLiqHeight[p+s]; + MapLiqHeight[k] = ChunkLiqHeight[p + s]; ++k; } - k=k+120; + k = k + 120; } delete []ChunkLiqHeight; break; @@ -291,10 +303,10 @@ inline void LoadMapChunk(MPQFile & mf, chunk*_chunk) double solve (vec *v,vec *p) { - double a = v[0].y *(v[1].z - v[2].z) + v[1].y *(v[2].z - v[0].z) + v[2].y *(v[0].z - v[1].z); - double b = v[0].z *(v[1].x - v[2].x) + v[1].z *(v[2].x - v[0].x) + v[2].z *(v[0].x - v[1].x); - double c = v[0].x *(v[1].y - v[2].y) + v[1].x *(v[2].y - v[0].y) + v[2].x *(v[0].y - v[1].y); - double d = v[0].x *(v[1].y*v[2].z - v[2].y*v[1].z) + v[1].x* (v[2].y*v[0].z - v[0].y*v[2].z) + v[2].x* (v[0].y*v[1].z - v[1].y*v[0].z); + double a = v[0].y * (v[1].z - v[2].z) + v[1].y * (v[2].z - v[0].z) + v[2].y * (v[0].z - v[1].z); + double b = v[0].z * (v[1].x - v[2].x) + v[1].z * (v[2].x - v[0].x) + v[2].z * (v[0].x - v[1].x); + double c = v[0].x * (v[1].y - v[2].y) + v[1].x * (v[2].y - v[0].y) + v[2].x * (v[0].y - v[1].y); + double d = v[0].x * (v[1].y * v[2].z - v[2].y * v[1].z) + v[1].x * (v[2].y * v[0].z - v[0].y * v[2].z) + v[2].x * (v[0].y * v[1].z - v[1].y * v[0].z); // -d // plane equation ax+by+cz+d=0 @@ -307,66 +319,66 @@ inline double GetZ(double x, double z) vec p; { // find out quadrant - int xc=(int)(x/UNITSIZE); - int zc=(int)(z/UNITSIZE); - if(xc>127)xc=127; - if(zc>127)zc=127; + int xc = (int)(x / UNITSIZE); + int zc = (int)(z / UNITSIZE); + if(xc > 127) xc = 127; + if(zc > 127) zc = 127; - double lx=x-xc*UNITSIZE; - double lz=z-zc*UNITSIZE; - p.x=lx; - p.z=lz; + double lx = x - xc * UNITSIZE; + double lz = z - zc * UNITSIZE; + p.x = lx; + p.z = lz; - v[0].x=UNITSIZE/2; - v[0].y =cell->v8[xc][zc]; - v[0].z=UNITSIZE/2; + v[0].x = UNITSIZE / 2; + v[0].y = cell->v8[xc][zc]; + v[0].z = UNITSIZE / 2; - if(lx>lz) + if(lx > lz) { - v[1].x=UNITSIZE; - v[1].y =cell->v9[xc+1][zc]; - v[1].z=0; + v[1].x = UNITSIZE; + v[1].y = cell->v9[xc + 1][zc]; + v[1].z = 0.0f; } else { - v[1].x=0.0; - v[1].y =cell->v9[xc][zc+1]; - v[1].z=UNITSIZE; + v[1].x = 0.0f; + v[1].y = cell->v9[xc][zc + 1]; + v[1].z = UNITSIZE; } - if(lz>UNITSIZE-lx) + if(lz > UNITSIZE - lx) { - v[2].x=UNITSIZE; - v[2].y =cell->v9[xc+1][zc+1]; - v[2].z=UNITSIZE; + v[2].x = UNITSIZE; + v[2].y = cell->v9[xc + 1][zc + 1]; + v[2].z = UNITSIZE; } else { - v[2].x=0; - v[2].y=cell->v9[xc][zc]; - v[2].z=0; + v[2].x = 0.0f; + v[2].y = cell->v9[xc][zc]; + v[2].z = 0.0f; } - return -solve(v,&p); + return -solve(v, &p); } } inline void TransformData() { - cell= new Cell; + cell = new Cell; - for(int x=0;x<128;++x) + for(uint32 x = 0; x < 128; ++x) { - for(int y=0;y<128;++y) + for(uint32 y = 0; y < 128; ++y) { - cell->v8[x][y] = (float)mcells->ch[x/8][y/8].v8[x%8][y%8]; - cell->v9[x][y] = (float)mcells->ch[x/8][y/8].v9[x%8][y%8]; + cell->v8[x][y] = (float)mcells->ch[x / 8][y / 8].v8[x % 8][y % 8]; + cell->v9[x][y] = (float)mcells->ch[x / 8][y / 8].v9[x % 8][y % 8]; } // extra 1 point on bounds - cell->v9[x][128] = (float)mcells->ch[x/8][15].v9[x%8][8]; - // x==y - cell->v9[128][x] = (float)mcells->ch[15][x/8].v9[8][x%8]; + cell->v9[x][128] = (float)mcells->ch[x / 8][15].v9[x % 8][8]; + // x == y + cell->v9[128][x] = (float)mcells->ch[15][x / 8].v9[8][x % 8]; } @@ -378,70 +390,59 @@ inline void TransformData() const char MAP_MAGIC[] = "MAP_2.01"; -bool ConvertADT(char * filename,char * filename2) +bool ConvertADT(char *filename, char *filename2) { - MapLiqHeight = new float[16384]; - MapLiqFlag = new char[256]; - for(int j = 0; j < 256; ++j) - MapLiqFlag[j] = 0; - for(int j = 0; j < 16384; ++j) - MapLiqHeight[j] = -999999; - if(!LoadADT(filename)) - { - delete [] MapLiqHeight; - delete [] MapLiqFlag; return false; - } - FILE *output=fopen(filename2,"wb"); + FILE *output=fopen(filename2, "wb"); if(!output) { - printf("Can't create the output file '%s'\n",filename2); + printf("Can't create the output file '%s'\n", filename2); delete [] MapLiqHeight; delete [] MapLiqFlag; return false; } // write magic header - fwrite(MAP_MAGIC,1,8,output); + fwrite(MAP_MAGIC, 1, 8, output); - for(unsigned int x=0;x<16;++x) + for(uint32 x = 0; x < 16; ++x) { - for(unsigned int y=0;y<16;++y) + for(uint32 y = 0; y < 16; ++y) { if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id <= maxAreaId) { - if(areas[mcells->ch[y][x].area_id]==0xffff) - printf("\nCan't find area flag for areaid %u.\n",mcells->ch[y][x].area_id); + if(areas[mcells->ch[y][x].area_id] == 0xffff) + printf("\nCan't find area flag for areaid %u.\n", mcells->ch[y][x].area_id); - fwrite(&areas[mcells->ch[y][x].area_id],1,2,output); + fwrite(&areas[mcells->ch[y][x].area_id], 1, 2, output); } else { - uint16 flag=0xffff; - fwrite(&flag,1,2,output); + uint16 flag = 0xffff; + fwrite(&flag, 1, 2, output); } } } - fwrite(MapLiqFlag,1,256,output); + fwrite(MapLiqFlag, 1, 256, output); delete [] MapLiqFlag; - - fwrite(MapLiqHeight,sizeof(float),16384,output); + + fwrite(MapLiqHeight, sizeof(float), 16384, output); delete [] MapLiqHeight; - + TransformData(); - for(unsigned int x=0;x Date: Sat, 6 Dec 2008 20:55:18 +0100 Subject: [PATCH 144/256] Fixed extractor build on *nix --- contrib/extractor/adt.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/extractor/adt.h b/contrib/extractor/adt.h index db2dade23..7fb8dc078 100644 --- a/contrib/extractor/adt.h +++ b/contrib/extractor/adt.h @@ -92,10 +92,10 @@ typedef struct { uint16 type; float heightLevel1; float heightLevel2; - byte xOffset; - byte yOffset; - byte width; - byte height; + uint8 xOffset; + uint8 yOffset; + uint8 width; + uint8 height; uint32 ofsData2a; uint32 ofsData2b; } MH2O_Data1; From 916bd178a237a45fa4b73c81775a867d63ede30f Mon Sep 17 00:00:00 2001 From: DiSlord Date: Mon, 8 Dec 2008 23:19:57 +0300 Subject: [PATCH 145/256] * Fixed some comments in code Signed-off-by: DiSlord --- src/game/SharedDefines.h | 58 ++++++++++++++++++------------------- src/game/SpellAuraDefines.h | 10 +++---- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 04452f02f..52614c265 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -202,7 +202,7 @@ enum ItemQualities #define SPELL_ATTR_UNK0 0x00000001 // 0 #define SPELL_ATTR_RANGED 0x00000002 // 1 All ranged abilites 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 +257,7 @@ enum ItemQualities #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 @@ -273,14 +273,14 @@ enum ItemQualities #define SPELL_ATTR_EX2_UNK5 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_UNK16 0x00010000 // 16 #define SPELL_ATTR_EX2_UNK17 0x00020000 // 17 Hunters Shot and Stings only have this flag #define SPELL_ATTR_EX2_UNK18 0x00040000 // 18 Only Revive pet - possible req dead pet @@ -398,37 +398,37 @@ enum ItemQualities #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 enum SheathTypes { @@ -662,10 +662,10 @@ enum SpellEffects SPELL_EFFECT_153 = 153, SPELL_EFFECT_154 = 154, SPELL_EFFECT_155 = 155, - SPELL_EFFECT_156 = 156, + SPELL_EFFECT_ADD_SOCKET = 156, SPELL_EFFECT_157 = 157, SPELL_EFFECT_MILLING = 158, - SPELL_EFFECT_159 = 159, + SPELL_EFFECT_ALLOW_RENAME_PET = 159, TOTAL_SPELL_EFFECTS = 160 }; diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index cd16eca68..f0100f8d7 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -310,7 +310,7 @@ enum AuraType SPELL_AURA_265 = 265, SPELL_AURA_266 = 266, SPELL_AURA_267 = 267, - SPELL_AURA_268 = 268, + SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268, SPELL_AURA_269 = 269, SPELL_AURA_270 = 270, SPELL_AURA_271 = 271, @@ -318,14 +318,14 @@ enum AuraType SPELL_AURA_273 = 273, SPELL_AURA_274 = 274, SPELL_AURA_275 = 275, - SPELL_AURA_276 = 276, + SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell SPELL_AURA_277 = 277, SPELL_AURA_278 = 278, SPELL_AURA_279 = 279, SPELL_AURA_280 = 280, - SPELL_AURA_281 = 281, - SPELL_AURA_282 = 282, - SPELL_AURA_283 = 283, + SPELL_AURA_MOD_HONOR_GAIN = 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 }; From 9b842b6fdc4f148d96d45fa68e01eadca8e04794 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Mon, 8 Dec 2008 23:22:39 +0300 Subject: [PATCH 146/256] Work under spell mods * Add support > 64 bit spellFamily mask * Remove not used fields in SpellModifier * Remove not used (and not correct work vs charges) GetTotalFlatMods, GetTotalPctMods * Use DBC based data for spell_affect * More better work SPELL_AURA_ADD_TARGET_TRIGGER aura Signed-off-by: DiSlord --- sql/wotlk_updates/9_mangos_spell_affect.sql | 12 ++++ src/game/Player.cpp | 49 +++---------- src/game/Player.h | 6 +- src/game/Spell.cpp | 6 +- src/game/Spell.h | 2 +- src/game/SpellAuras.cpp | 80 +++++++++++++++------ src/game/SpellAuras.h | 3 + src/game/SpellEffects.cpp | 4 +- src/game/SpellMgr.cpp | 77 ++++++++++---------- src/game/SpellMgr.h | 15 ++-- src/game/Unit.cpp | 10 +-- src/shared/Database/DBCStructure.h | 6 +- src/shared/Database/DBCfmt.cpp | 2 +- 13 files changed, 145 insertions(+), 127 deletions(-) create mode 100644 sql/wotlk_updates/9_mangos_spell_affect.sql diff --git a/sql/wotlk_updates/9_mangos_spell_affect.sql b/sql/wotlk_updates/9_mangos_spell_affect.sql new file mode 100644 index 000000000..20b9e987b --- /dev/null +++ b/sql/wotlk_updates/9_mangos_spell_affect.sql @@ -0,0 +1,12 @@ +-- +-- Table structure for table `spell_affect` +-- +DROP TABLE IF EXISTS `spell_affect`; +CREATE TABLE `spell_affect` ( + `entry` smallint(5) unsigned NOT NULL default '0', + `effectId` tinyint(3) unsigned NOT NULL default '0', + `SpellClassMask0` int(5) unsigned NOT NULL default '0', + `SpellClassMask1` int(5) unsigned NOT NULL default '0', + `SpellClassMask2` int(5) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`effectId`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 02de2c3f3..4e3dfa7f8 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -16361,42 +16361,6 @@ void Player::CharmSpellInitialize() 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) @@ -16414,22 +16378,25 @@ 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) + for(int eff=0;eff<96;++eff) { - uint64 _mask = uint64(1) << eff; - if ( mod->mask & _mask) + uint64 _mask = 0; + uint64 _mask2= 0; + if (eff<64) _mask = uint64(1) << (eff- 0); + else _mask2= uint64(1) << (eff-64); + if ( mod->mask & _mask || mod->mask2 & _mask2) { 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 || (*itr)->mask2 & _mask2)) val += (*itr)->value; } val += apply ? mod->value : -(mod->value); diff --git a/src/game/Player.h b/src/game/Player.h index 9035b0c8d..d6bfe28b3 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -80,15 +80,17 @@ struct PlayerSpell #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; + uint64 mask2; uint32 spellId; - uint32 effectId; Spell const* lastAffected; }; @@ -1483,8 +1485,6 @@ class MANGOS_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 T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell const* spell = NULL); void RemoveSpellMods(Spell const* spell); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 1727ca15e..895c585f3 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2521,7 +2521,7 @@ void Spell::finish(bool ok) { SpellEntry const *auraSpellInfo = (*i)->GetSpellProto(); uint32 auraSpellIdx = (*i)->GetEffIndex(); - if (IsAffectedBy(auraSpellInfo, auraSpellIdx)) + if (IsAffectedByAura((*i))) { for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) if( ihit->effectMask & (1<Id,effectId,spellInfo->EffectItemType[effectId]); + return spellmgr.IsAffectedByMod(m_spellInfo, aura->getAuraSpellMod()); } bool Spell::CheckTargetCreatureType(Unit* target) const diff --git a/src/game/Spell.h b/src/game/Spell.h index ac71da5b4..60c8fc83c 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -422,7 +422,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; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 1c7403246..0fca284ae 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -159,7 +159,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 @@ -1180,10 +1180,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; @@ -1204,15 +1200,25 @@ void Aura::HandleAddModifier(bool apply, bool Real) 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; + uint32 const *ptr; + SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex); + if (spellAffect) + ptr = spellAffect->SpellClassMask; else - mod->mask = spellInfo->EffectItemType[m_effIndex]; + { + switch (m_effIndex) + { + case 0: ptr = m_spellProto->EffectSpellClassMaskA; break; + case 1: ptr = m_spellProto->EffectSpellClassMaskB; break; + case 2: ptr = m_spellProto->EffectSpellClassMaskC; break; + default: + return; + } + } + + mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32; + mod->mask2= (uint64)ptr[2]; if (m_procCharges > 0) mod->charges = m_procCharges; @@ -1227,7 +1233,7 @@ void Aura::HandleAddModifier(bool apply, bool Real) ((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 && (spellFamilyMask & 0x0000100000000000LL)) { m_target->RemoveAurasDueToSpell(45471); @@ -1235,7 +1241,42 @@ 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(); + uint32 const *ptr; + SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex); + if (spellAffect) + ptr = spellAffect->SpellClassMask; + else + { + switch (m_effIndex) + { + case 0: ptr = m_spellProto->EffectSpellClassMaskA; break; + case 1: ptr = m_spellProto->EffectSpellClassMaskB; break; + case 2: ptr = m_spellProto->EffectSpellClassMaskC; break; + default: + return; + } + } + + mod->mask = (uint64)ptr[0] | (uint64)ptr[1]<<32; + mod->mask2= (uint64)ptr[2]; + m_spellmod = mod; + } + else + { + delete m_spellmod; + m_spellmod = NULL; + } +} void Aura::TriggerSpell() { Unit* caster = GetCaster(); @@ -2193,10 +2234,8 @@ 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->mask2= 0LL; m_spellmod = mod; } @@ -2219,10 +2258,8 @@ 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->mask2= 0LL; m_spellmod = mod; } @@ -2244,18 +2281,17 @@ 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->mask2= 0LL; break; case 1: mod->mask = 0x00400000000LL; // Flametongue Totem + mod->mask2= 0LL; break; } - mod->charges = 0; m_spellmod = mod; } diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 0a3fbd3d9..09ee97eb5 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -98,6 +98,7 @@ class MANGOS_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); @@ -230,6 +231,8 @@ class MANGOS_DLL_SPEC Aura void SetAuraDuration(int32 duration) { m_duration = duration; } time_t GetAuraApplyTime() { return m_applyTime; } + SpellModifier *getAuraSpellMod() {return m_spellmod; } + uint64 const& GetCasterGUID() const { return m_caster_guid; } Unit* GetCaster() const; Unit* GetTarget() const { return m_target; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 22a80571e..9da67aa43 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1524,10 +1524,8 @@ 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->mask2= 0LL; ((Player*)m_caster)->AddSpellMod(mod, true); m_caster->CastSpell(unitTarget,spell_proto,true,NULL); diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index b93aad5fc..46bb2a3db 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -666,8 +666,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 ) { @@ -714,26 +714,29 @@ void SpellMgr::LoadSpellAffects() continue; } - uint64 spellAffectMask = fields[2].GetUInt64(); + SpellAffectEntry affect; + affect.SpellClassMask[0] = fields[2].GetUInt32(); + affect.SpellClassMask[1] = fields[3].GetUInt32(); + affect.SpellClassMask[2] = fields[4].GetUInt32(); - // Spell.dbc have own data for low part of SpellFamilyMask - if( spellInfo->EffectItemType[effectId]) + // Spell.dbc have own data + uint32 const *ptr = 0; + switch (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); + case 0: ptr = spellInfo->EffectSpellClassMaskA; break; + case 1: ptr = spellInfo->EffectSpellClassMaskB; break; + case 2: ptr = spellInfo->EffectSpellClassMaskC; break; + default: 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; - } + } + if(ptr[0] == affect.SpellClassMask[0] || ptr[1] == affect.SpellClassMask[1] || ptr[2] == affect.SpellClassMask[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() ); @@ -741,7 +744,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) { @@ -757,7 +760,16 @@ void SpellMgr::LoadSpellAffects() spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER) ) continue; - if(spellInfo->EffectItemType[effectId] != 0) + uint32 const *ptr = 0; + switch (effectId) + { + case 0: ptr = spellInfo->EffectSpellClassMaskA; break; + case 1: ptr = spellInfo->EffectSpellClassMaskB; break; + case 2: ptr = spellInfo->EffectSpellClassMaskC; break; + default: + continue; + } + if(ptr[0] || ptr[1] || ptr[2]) continue; if(mSpellAffectMap.find((id<<8) + effectId) != mSpellAffectMap.end()) @@ -768,33 +780,20 @@ 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 || + mod->mask2 & spellInfo->SpellFamilyFlags2) return true; return false; diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index e1913e1fe..9db1b1ee7 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -27,6 +27,9 @@ #include "Database/SQLStorage.h" #include "Utilities/UnorderedMap.h" + +#include "Player.h" + #include class Player; @@ -450,7 +453,11 @@ bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group); DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group); // Spell affects related declarations (accessed using SpellMgr functions) -typedef std::map SpellAffectMap; +struct SpellAffectEntry +{ + uint32 SpellClassMask[3]; +}; +typedef UNORDERED_MAP SpellAffectMap; // Spell proc event related declarations (accessed using SpellMgr functions) enum ProcFlags @@ -657,15 +664,15 @@ class SpellMgr // Accessors (const or static functions) public: // Spell affects - uint64 GetSpellAffectMask(uint16 spellId, uint8 effectId) const + SpellAffectEntry 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; } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 1fe3e984d..f03c2469c 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -5763,10 +5763,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu mod->value = -100; mod->type = SPELLMOD_PCT; mod->spellId = dummySpell->Id; - mod->effectId = 0; - mod->lastAffected = NULL; mod->mask = 0x0000000000000003LL; - mod->charges = 0; + mod->mask2= 0LL; ((Player*)this)->AddSpellMod(mod, true); // Remove cooldown (Chain Lightning - have Category Recovery time) @@ -10929,10 +10927,8 @@ 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; + mod->mask2 = spellProto->SpellFamilyFlags2; caster->AddSpellMod(mod, true); CastCustomSpell(target,spellProto->Id,&heal,NULL,NULL,true,NULL,triggeredByAura,caster->GetGUID()); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index b42d9c223..10fef5930 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -1110,9 +1110,9 @@ struct SpellEntry int32 EffectMiscValueB[3]; // 116-118 m_effectMiscValueB uint32 EffectTriggerSpell[3]; // 119-121 m_effectTriggerSpell float EffectPointsPerComboPoint[3]; // 122-124 m_effectPointsPerCombo - //uint32 EffectSpellClassMaskA[3]; // 125-127 m_effectSpellClassMaskA not used - //uint32 EffectSpellClassMaskB[3]; // 128-130 m_effectSpellClassMaskB not used - //uint32 EffectSpellClassMaskC[3]; // 131-133 m_effectSpellClassMaskC not used + uint32 EffectSpellClassMaskA[3]; // 125-127 m_effectSpellClassMaskA + uint32 EffectSpellClassMaskB[3]; // 128-130 m_effectSpellClassMaskB + uint32 EffectSpellClassMaskC[3]; // 131-133 m_effectSpellClassMaskC uint32 SpellVisual[2]; // 134-135 m_spellVisualID uint32 SpellIconID; // 136 m_spellIconID uint32 activeIconID; // 137 m_activeIconID diff --git a/src/shared/Database/DBCfmt.cpp b/src/shared/Database/DBCfmt.cpp index 4ccbf54c8..b78608c2d 100644 --- a/src/shared/Database/DBCfmt.cpp +++ b/src/shared/Database/DBCfmt.cpp @@ -69,7 +69,7 @@ const char SkillLineAbilityfmt[]="niiiixxiiiiixx"; const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; const char SpellCastTimefmt[]="nixx"; const char SpellDurationfmt[]="niii"; -const char SpellEntryfmt[]="niiiiiiiiixiiiiiiiiiixxxxiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffxxxxxxxxxiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiix"; +const char SpellEntryfmt[]="niiiiiiiiixiiiiiiiiiixxxxiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiix"; const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx"; const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiixx"; const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX"; From c78b5644c7f1db51788b4bcf2c995433427db655 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 6 Dec 2008 01:24:55 +0300 Subject: [PATCH 147/256] [6874] * Not remove spell mods for not finished spells * Ignore self miss in drop combopoints (problems vs 5171 and ranks still exist) * Allow cast spell on immune if spell can removeit by dispell --- src/game/Spell.cpp | 13 +++++++------ src/game/Unit.cpp | 3 ++- src/shared/revision_nr.h | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 895c585f3..7be354825 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -2507,14 +2507,14 @@ void Spell::finish(bool ok) m_spellState = SPELL_STATE_FINISHED; - //remove spell mods - if (m_caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_caster)->RemoveSpellMods(this); - // other code related only to successfully finished spells if(!ok) return; + //remove spell mods + if (m_caster->GetTypeId() == TYPEID_PLAYER) + ((Player*)m_caster)->RemoveSpellMods(this); + //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) @@ -2553,10 +2553,11 @@ void Spell::finish(bool ok) // Clear combo at finish state if(m_caster->GetTypeId() == TYPEID_PLAYER && NeedsComboPoints(m_spellInfo)) { - // Not drop combopoints if any miss exist + // Not drop combopoints if negative spell and if any miss on enemy exist bool needDrop = true; + if (!IsPositiveSpell(m_spellInfo->Id)) for(std::list::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) - if (ihit->missCondition != SPELL_MISS_NONE) + if (ihit->missCondition != SPELL_MISS_NONE && ihit->targetGUID!=m_caster->GetGUID()) { needDrop = false; break; diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index f03c2469c..82e1c33ec 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -8062,7 +8062,8 @@ bool Unit::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) if(itr->type == spellInfo->Dispel) return true; - if( !(spellInfo->AttributesEx & SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE)) // unaffected by school immunity + if( !(spellInfo->AttributesEx & SPELL_ATTR_EX_UNAFFECTED_BY_SCHOOL_IMMUNE) && // unaffected by school immunity + !(spellInfo->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY)) // can remove immune (by dispell or immune it) { // not have spells with charges currently SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL]; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 169735a48..1b521491b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6873" + #define REVISION_NR "6874" #endif // __REVISION_NR_H__ From b6a5767902befb38d75bbfbe0400a328cdcc3fbd Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 6 Dec 2008 02:44:39 +0300 Subject: [PATCH 148/256] [6875] Skip utf8 header (if exist) for mangosd.conf file --- src/shared/Config/dotconfpp/dotconfpp.cpp | 5 +++++ src/shared/revision_nr.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/shared/Config/dotconfpp/dotconfpp.cpp b/src/shared/Config/dotconfpp/dotconfpp.cpp index 60008747a..1c5e667b1 100644 --- a/src/shared/Config/dotconfpp/dotconfpp.cpp +++ b/src/shared/Config/dotconfpp/dotconfpp.cpp @@ -340,6 +340,11 @@ int DOTCONFDocument::setContent(const char * _fileName) error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno)); return -1; } + // Try read utf8 header and skip it if exist + uint32 utf8header = 0; + fgets((char*)&utf8header, 4, file); // Try read header + if (utf8header!=0x00BFBBEF) // If not exist + fseek(file, 0, SEEK_SET); // Reset read position ret = parseFile(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1b521491b..2c90a0670 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6874" + #define REVISION_NR "6875" #endif // __REVISION_NR_H__ From 1ff2b7fc8b7bf863d28a1fffb4459affa4035b7e Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 6 Dec 2008 04:38:31 +0300 Subject: [PATCH 149/256] [6876] * Not drop charge for 1120 and ranks (fix SPELL_AURA_CHANNEL_DEATH_ITEM aura work) --- src/game/Unit.cpp | 11 ++++------- src/shared/revision_nr.h | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 82e1c33ec..a51c91236 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -6016,17 +6016,14 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB { int32 value2 = CalculateSpellDamage((*i)->GetSpellProto(),2,(*i)->GetSpellProto()->EffectBasePoints[2],this); basepoints0 = value2 * GetMaxPower(POWER_MANA) / 100; - // Drain Soul - triggered_spell_id = 18371; - target = this; - found = true; + CastCustomSpell(this, 18371, &basepoints0, NULL, NULL, true, castItem, triggeredByAura); break; } } - if(!found) - return false; - break; // fall through to normal cast + // 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; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 2c90a0670..a20708ae8 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6875" + #define REVISION_NR "6876" #endif // __REVISION_NR_H__ From ca5278ba6e2a4699ed31febcd3232c6417f50cc8 Mon Sep 17 00:00:00 2001 From: megamage Date: Sat, 6 Dec 2008 04:48:39 +0300 Subject: [PATCH 150/256] [6877] Fix Prayer of Mending. Use original caster's healing bonus. --- src/game/SpellEffects.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 9da67aa43..44f69dc02 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2199,7 +2199,7 @@ void Spell::EffectApplyAura(uint32 i) // Prayer of Mending (jump animation), we need formal caster instead original for correct animation if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL)) - m_caster->CastSpell(unitTarget,41637,true,NULL,Aur); + m_caster->CastSpell(unitTarget, 41637, true, NULL, Aur, m_originalCasterGUID); } void Spell::EffectUnlearnSpecialization( uint32 i ) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a20708ae8..c2c949764 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6876" + #define REVISION_NR "6877" #endif // __REVISION_NR_H__ From 8ae33af8f61616dc0a31e0517372dbfbfc42f6d9 Mon Sep 17 00:00:00 2001 From: Neo2003 Date: Sat, 6 Dec 2008 00:28:09 +0100 Subject: [PATCH 151/256] [6878] Fixed a typo in VC for ACE_Wrappers Signed-off-by: freghar (cherry picked from commit d94f03b0aeec431ec6cee4f469d45d3209434fe7) Signed-off-by: VladimirMangos --- src/shared/revision_nr.h | 2 +- win/mangosdVC71.sln | 2 +- win/mangosdVC80.sln | 2 +- win/mangosdVC90.sln | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c2c949764..53d0f4b8d 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6877" + #define REVISION_NR "6878" #endif // __REVISION_NR_H__ diff --git a/win/mangosdVC71.sln b/win/mangosdVC71.sln index 9b71ab7df..3d5ba3ccb 100644 --- a/win/mangosdVC71.sln +++ b/win/mangosdVC71.sln @@ -61,7 +61,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "genrevision", "VC71\genrevi ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ACE_Wraper", "VC71\ACE_vc71.vcproj", "{7C74F49E-FECA-1BAD-6757-8A6348EA12C8}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ACE_Wrappers", "VC71\ACE_vc71.vcproj", "{7C74F49E-FECA-1BAD-6757-8A6348EA12C8}" ProjectSection(ProjectDependencies) = postProject EndProjectSection EndProject diff --git a/win/mangosdVC80.sln b/win/mangosdVC80.sln index 664fe3f6b..4440cd0b8 100644 --- a/win/mangosdVC80.sln +++ b/win/mangosdVC80.sln @@ -46,7 +46,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sockets", "VC80\sockets.vcp EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "genrevision", "VC80\genrevision.vcproj", "{803F488E-4C5A-4866-8D5C-1E6C03C007C2}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ACEWraper", "VC80\ACE_vc8.vcproj", "{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ACE_Wrappers", "VC80\ACE_vc8.vcproj", "{AD537C9A-FECA-1BAD-6757-8A6348EA12C8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/win/mangosdVC90.sln b/win/mangosdVC90.sln index 5c3ba4c1d..02a13a939 100644 --- a/win/mangosdVC90.sln +++ b/win/mangosdVC90.sln @@ -46,7 +46,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sockets", "VC90\sockets.vcp EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "genrevision", "VC90\genrevision.vcproj", "{803F488E-4C5A-4866-8D5C-1E6C03C007C2}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ACEWraper", "VC90\ACE_vc9.vcproj", "{BD537C9A-FECA-1BAD-6757-8A6348EA12C8}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ACE_Wrappers", "VC90\ACE_vc9.vcproj", "{BD537C9A-FECA-1BAD-6757-8A6348EA12C8}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution From fdd4fcd48f3781120d8d84e662839f135af46a3b Mon Sep 17 00:00:00 2001 From: thenecromancer Date: Sat, 6 Dec 2008 08:03:42 +0300 Subject: [PATCH 152/256] Set correct base damage for spell 37674 Signed-off-by: VladimirMangos --- src/game/SpellEffects.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 44f69dc02..a83653962 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -996,9 +996,14 @@ void Spell::EffectDummy(uint32 i) return; } case 37674: // Chaos Blast - if(unitTarget) - m_caster->CastSpell(unitTarget,37675,true); + { + if(!unitTarget) + return; + + int32 basepoints0 = 100; + m_caster->CastCustomSpell(unitTarget,37675,&basepoints0,NULL,NULL,true); return; + } case 40802: // Mingo's Fortune Generator (Mingo's Fortune Giblets) { // selecting one from Bloodstained Fortune item From 52da5abf4d449768f7174b731124b63845d0bf18 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 6 Dec 2008 08:05:00 +0300 Subject: [PATCH 153/256] [6879] Not apply casting time spell bonuses mods to creature (non-pets) casted spells with 0 cast time. --- src/game/Unit.cpp | 4 ++++ src/shared/revision_nr.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index a51c91236..43d993b2a 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -10612,6 +10612,10 @@ void Unit::ApplyCastTimePercentMod(float val, bool apply ) uint32 Unit::GetCastingTimeForBonus( SpellEntry const *spellProto, DamageEffectType damagetype, uint32 CastingTime ) { + // Not apply this to creature casted spells with casttime==0 + if(CastingTime==0 && GetTypeId()==TYPEID_UNIT && !((Creature*)this)->isPet()) + return 3500; + if (CastingTime > 7000) CastingTime = 7000; if (CastingTime < 1500) CastingTime = 1500; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 53d0f4b8d..cfb991ff2 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6878" + #define REVISION_NR "6879" #endif // __REVISION_NR_H__ From 26d1574eb1abfd2e4bdce18be9b41317d2914126 Mon Sep 17 00:00:00 2001 From: DasBlub Date: Sat, 6 Dec 2008 14:25:00 +0100 Subject: [PATCH 154/256] [6880] fixed spell 26275 for game object 180797 Signed-off-by: arrai --- src/game/SpellEffects.cpp | 32 ++++++++++++++++++++++++++++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index a83653962..b15ffecba 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -4593,6 +4593,38 @@ void Spell::EffectScriptEffect(uint32 effIndex) // by spell id switch(m_spellInfo->Id) { + // PX-238 Winter Wondervolt TRAP + case 26275: + { + if( unitTarget->HasAura(26272,0) + || unitTarget->HasAura(26157,0) + || unitTarget->HasAura(26273,0) + || unitTarget->HasAura(26274,0)) + return; + + uint32 iTmpSpellId; + + switch(urand(0,3)) + { + case 0: + iTmpSpellId = 26272; + break; + case 1: + iTmpSpellId = 26157; + break; + case 2: + iTmpSpellId = 26273; + break; + case 3: + iTmpSpellId = 26274; + break; + } + + unitTarget->CastSpell(unitTarget, iTmpSpellId, true); + + return; + } + // Bending Shinbone case 8856: { diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index cfb991ff2..c726f0830 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6879" + #define REVISION_NR "6880" #endif // __REVISION_NR_H__ From 99ccdd51b0632288a2f94e8fe4e49a75dd251439 Mon Sep 17 00:00:00 2001 From: GalaxyMan Date: Sat, 6 Dec 2008 21:40:36 +0300 Subject: [PATCH 155/256] [6881] Fix typo in log string. Signed-off-by: VladimirMangos --- src/game/WorldSocketMgr.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/WorldSocketMgr.cpp b/src/game/WorldSocketMgr.cpp index 9bb11f8fe..610d0ac57 100644 --- a/src/game/WorldSocketMgr.cpp +++ b/src/game/WorldSocketMgr.cpp @@ -242,7 +242,7 @@ WorldSocketMgr::StartReactiveIO (ACE_UINT16 port, const char* address) m_NetThreads = new ReactorRunnable[m_NetThreadsCount]; - sLog.outBasic ("Max alowed socket connections %d",ACE::max_handles ()); + sLog.outBasic ("Max allowed socket connections %d",ACE::max_handles ()); // -1 means use default m_SockOutKBuff = sConfig.GetIntDefault ("Network.OutKBuff", -1); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c726f0830..3cb4a4262 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6880" + #define REVISION_NR "6881" #endif // __REVISION_NR_H__ From c7aef1a8c86b5443081907962008ab7e568d9f1a Mon Sep 17 00:00:00 2001 From: hunuza Date: Sun, 7 Dec 2008 13:19:16 +0100 Subject: [PATCH 156/256] [6882] Make corpse erase async. --- src/game/GlobalEvents.cpp | 79 ++++++++++++++++++++------------------- src/shared/revision_nr.h | 2 +- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/game/GlobalEvents.cpp b/src/game/GlobalEvents.cpp index 14ad25607..697c55b1f 100644 --- a/src/game/GlobalEvents.cpp +++ b/src/game/GlobalEvents.cpp @@ -29,49 +29,52 @@ #include "ObjectDefines.h" #include "Corpse.h" +static void CorpsesEraseCallBack(QueryResult *result, bool bones) +{ + if(!result) + return; + + do + { + Field *fields = result->Fetch(); + uint32 guidlow = fields[0].GetUInt32(); + float positionX = fields[1].GetFloat(); + float positionY = fields[2].GetFloat(); + uint32 mapid = fields[3].GetUInt32(); + uint64 player_guid = MAKE_NEW_GUID(fields[4].GetUInt32(), 0, HIGHGUID_PLAYER); + + uint64 guid = MAKE_NEW_GUID(guidlow, 0, HIGHGUID_CORPSE); + + sLog.outDebug("[Global event] Removing %s %u (X:%f Y:%f Map:%u).",(bones?"bones":"corpse"),guidlow,positionX,positionY,mapid); + + /// Resurrectable - convert corpses to bones + if(!bones) + { + if(!ObjectAccessor::Instance().ConvertCorpseForPlayer(player_guid)) + { + sLog.outDebug("Corpse %u not found in world. Delete from DB.",guidlow); + CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow); + } + } + else + ///- or delete bones + { + MapManager::Instance().RemoveBonesFromMap(mapid, guid, positionX, positionY); + + ///- remove bones from the database + CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow); + } + } while (result->NextRow()); + + delete result; +} + /// Handle periodic erase of corpses and bones static void CorpsesErase(bool bones,uint32 delay) { ///- Get the list of eligible corpses/bones to be removed //No SQL injection (uint32 and enum) - QueryResult *result = CharacterDatabase.PQuery("SELECT guid,position_x,position_y,map,player FROM corpse WHERE UNIX_TIMESTAMP()-time > '%u' AND corpse_type %s '0'", delay, (bones ? "=" : "<>") ); - - if(result) - { - do - { - Field *fields = result->Fetch(); - uint32 guidlow = fields[0].GetUInt32(); - float positionX = fields[1].GetFloat(); - float positionY = fields[2].GetFloat(); - uint32 mapid = fields[3].GetUInt32(); - uint64 player_guid = MAKE_NEW_GUID(fields[4].GetUInt32(), 0, HIGHGUID_PLAYER); - - uint64 guid = MAKE_NEW_GUID(guidlow, 0, HIGHGUID_CORPSE); - - sLog.outDebug("[Global event] Removing %s %u (X:%f Y:%f Map:%u).",(bones?"bones":"corpse"),guidlow,positionX,positionY,mapid); - - /// Resurrectable - convert corpses to bones - if(!bones) - { - if(!ObjectAccessor::Instance().ConvertCorpseForPlayer(player_guid)) - { - sLog.outDebug("Corpse %u not found in world. Delete from DB.",guidlow); - CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow); - } - } - else - ///- or delete bones - { - MapManager::Instance().RemoveBonesFromMap(mapid, guid, positionX, positionY); - - ///- remove bones from the database - CharacterDatabase.PExecute("DELETE FROM corpse WHERE guid = '%u'",guidlow); - } - } while (result->NextRow()); - - delete result; - } + CharacterDatabase.AsyncPQuery(&CorpsesEraseCallBack, bones, "SELECT guid,position_x,position_y,map,player FROM corpse WHERE UNIX_TIMESTAMP()-time > '%u' AND corpse_type %s '0'", delay, (bones ? "=" : "<>")); } /// not thread guarded variant for call from other thread diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3cb4a4262..1311b2733 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6881" + #define REVISION_NR "6882" #endif // __REVISION_NR_H__ From a94b918ffcdb0b6b504292f7b417fc0c1ba63616 Mon Sep 17 00:00:00 2001 From: hunuza Date: Sun, 7 Dec 2008 15:41:05 +0100 Subject: [PATCH 157/256] [6883] Avoid DB access on deleting guild member. --- src/game/GlobalEvents.cpp | 1 + src/game/Guild.cpp | 76 +++++++++++++++++++-------------------- src/shared/revision_nr.h | 2 +- 3 files changed, 40 insertions(+), 39 deletions(-) diff --git a/src/game/GlobalEvents.cpp b/src/game/GlobalEvents.cpp index 697c55b1f..219086c61 100644 --- a/src/game/GlobalEvents.cpp +++ b/src/game/GlobalEvents.cpp @@ -22,6 +22,7 @@ #include "Log.h" #include "Database/DatabaseEnv.h" +#include "Database/DatabaseImpl.h" #include "Platform/Define.h" #include "MapManager.h" #include "ObjectAccessor.h" diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index af0de3c08..f4cc438e6 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -417,53 +417,53 @@ void Guild::DelMember(uint64 guid, bool isDisbanding) { if(leaderGuid == guid && !isDisbanding) { - QueryResult *result = CharacterDatabase.PQuery("SELECT guid FROM guild_member WHERE guildid='%u' AND guid != '%u' ORDER BY rank ASC LIMIT 1", Id, GUID_LOPART(leaderGuid)); - if( result ) + MemberSlot* oldLeader = NULL; + MemberSlot* best = NULL; + uint64 newLeaderGUID = 0; + for(Guild::MemberList::iterator i = members.begin(); i != members.end(); ++i) { - uint64 newLeaderGUID; - Player *newLeader; - std::string newLeaderName, oldLeaderName; - - newLeaderGUID = (*result)[0].GetUInt64(); - delete result; - - SetLeader(newLeaderGUID); - - newLeader = objmgr.GetPlayer(newLeaderGUID); - - // If player not online data in data field will be loaded from guild tabs no need to update it !! - if(newLeader) + if(i->first == GUID_LOPART(guid)) { - newLeader->SetRank(GR_GUILDMASTER); - newLeaderName = newLeader->GetName(); - } - else - objmgr.GetPlayerNameByGUID(newLeaderGUID, newLeaderName); - - // when leader non-exist (at guild load with deleted leader only) not send broadcasts - if(objmgr.GetPlayerNameByGUID(guid, oldLeaderName)) - { - WorldPacket data(SMSG_GUILD_EVENT, (1+1+oldLeaderName.size()+1+newLeaderName.size()+1)); - data << (uint8)GE_LEADER_CHANGED; - data << (uint8)2; - data << oldLeaderName; - data << newLeaderName; - BroadcastPacket(&data); - - data.Initialize(SMSG_GUILD_EVENT, (1+1+oldLeaderName.size()+1)); - data << (uint8)GE_LEFT; - data << (uint8)1; - data << oldLeaderName; - BroadcastPacket(&data); + oldLeader = &(i->second); + continue; } - sLog.outDebug( "WORLD: Sent (SMSG_GUILD_EVENT)" ); + if(!best || best->RankId > i->second.RankId) + { + best = &(i->second); + newLeaderGUID = i->first; + } } - else + if(!best) { Disband(); return; } + + SetLeader(newLeaderGUID); + + // If player not online data in data field will be loaded from guild tabs no need to update it !! + if(Player *newLeader = objmgr.GetPlayer(newLeaderGUID)) + newLeader->SetRank(GR_GUILDMASTER); + + // when leader non-exist (at guild load with deleted leader only) not send broadcasts + if(oldLeader) + { + WorldPacket data(SMSG_GUILD_EVENT, (1+1+(oldLeader->name).size()+1+(best->name).size()+1)); + data << (uint8)GE_LEADER_CHANGED; + data << (uint8)2; + data << oldLeader->name; + data << best->name; + BroadcastPacket(&data); + + data.Initialize(SMSG_GUILD_EVENT, (1+1+(oldLeader->name).size()+1)); + data << (uint8)GE_LEFT; + data << (uint8)1; + data << oldLeader->name; + BroadcastPacket(&data); + } + + sLog.outDebug( "WORLD: Sent (SMSG_GUILD_EVENT)" ); } members.erase(GUID_LOPART(guid)); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1311b2733..c66531390 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6882" + #define REVISION_NR "6883" #endif // __REVISION_NR_H__ From 6cee03bae09026a06e505366863a3c2e514ffee9 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 9 Dec 2008 08:28:42 +0300 Subject: [PATCH 158/256] Fixed build after merge. --- src/game/SpellAuras.cpp | 16 ++++++++-------- src/game/SpellMgr.cpp | 12 ++++++------ src/game/Traveller.h | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 04ed6a32d..519e28ad0 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1204,14 +1204,14 @@ void Aura::HandleAddModifier(bool apply, bool Real) uint32 const *ptr; SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex); if (spellAffect) - ptr = spellAffect->SpellClassMask; + ptr = &spellAffect->SpellClassMask[0]; else { switch (m_effIndex) { - case 0: ptr = m_spellProto->EffectSpellClassMaskA; break; - case 1: ptr = m_spellProto->EffectSpellClassMaskB; break; - case 2: ptr = m_spellProto->EffectSpellClassMaskC; break; + case 0: ptr = &m_spellProto->EffectSpellClassMaskA[0]; break; + case 1: ptr = &m_spellProto->EffectSpellClassMaskB[0]; break; + case 2: ptr = &m_spellProto->EffectSpellClassMaskC[0]; break; default: return; } @@ -1254,14 +1254,14 @@ void Aura::HandleAddTargetTrigger(bool apply, bool Real) uint32 const *ptr; SpellAffectEntry const *spellAffect = spellmgr.GetSpellAffect(GetId(), m_effIndex); if (spellAffect) - ptr = spellAffect->SpellClassMask; + ptr = &spellAffect->SpellClassMask[0]; else { switch (m_effIndex) { - case 0: ptr = m_spellProto->EffectSpellClassMaskA; break; - case 1: ptr = m_spellProto->EffectSpellClassMaskB; break; - case 2: ptr = m_spellProto->EffectSpellClassMaskC; break; + case 0: ptr = &m_spellProto->EffectSpellClassMaskA[0]; break; + case 1: ptr = &m_spellProto->EffectSpellClassMaskB[0]; break; + case 2: ptr = &m_spellProto->EffectSpellClassMaskC[0]; break; default: return; } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 46bb2a3db..0054842bd 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -723,9 +723,9 @@ void SpellMgr::LoadSpellAffects() uint32 const *ptr = 0; switch (effectId) { - case 0: ptr = spellInfo->EffectSpellClassMaskA; break; - case 1: ptr = spellInfo->EffectSpellClassMaskB; break; - case 2: ptr = spellInfo->EffectSpellClassMaskC; break; + case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break; + case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break; + case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break; default: continue; } @@ -763,9 +763,9 @@ void SpellMgr::LoadSpellAffects() uint32 const *ptr = 0; switch (effectId) { - case 0: ptr = spellInfo->EffectSpellClassMaskA; break; - case 1: ptr = spellInfo->EffectSpellClassMaskB; break; - case 2: ptr = spellInfo->EffectSpellClassMaskC; break; + case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break; + case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break; + case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break; default: continue; } diff --git a/src/game/Traveller.h b/src/game/Traveller.h index 9256b9162..2d112896f 100644 --- a/src/game/Traveller.h +++ b/src/game/Traveller.h @@ -62,7 +62,7 @@ inline float Traveller::Speed() if(i_traveller.HasUnitMovementFlag(MOVEMENTFLAG_WALK_MODE)) return i_traveller.GetSpeed(MOVE_WALK); else if(i_traveller.HasUnitMovementFlag(MOVEMENTFLAG_FLYING2)) - return i_traveller.GetSpeed(MOVE_FLY); + return i_traveller.GetSpeed(MOVE_FLIGHT); else return i_traveller.GetSpeed(MOVE_RUN); } From 82cbd9152d51befdaaa7894752df4c14d1bb2aec Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 9 Dec 2008 11:47:49 +0300 Subject: [PATCH 159/256] Fixed possible crash in Aura::HandleModPossessPet Also small code cleanup. --- src/game/Pet.cpp | 32 ++++++++++++++++++-------------- src/game/SpellAuras.cpp | 5 ++++- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index ef5898b2c..2dbdd5dc8 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -1524,24 +1524,28 @@ void Pet::ToggleAutocast(uint32 spellid, bool apply) if(apply) { - for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++); - if (i == m_autospells.size()) - { - m_autospells.push_back(spellid); - itr->second->active = ACT_ENABLED; - itr->second->state = PETSPELL_CHANGED; - } + for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++) + ; // just search + + if (i == m_autospells.size()) + { + m_autospells.push_back(spellid); + itr->second->active = ACT_ENABLED; + itr->second->state = PETSPELL_CHANGED; + } } else { AutoSpellList::iterator itr2 = m_autospells.begin(); - for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++); - if (i < m_autospells.size()) - { - m_autospells.erase(itr2); - itr->second->active = ACT_DISABLED; - itr->second->state = PETSPELL_CHANGED; - } + for (i = 0; i < m_autospells.size() && m_autospells[i] != spellid; i++, itr2++) + ; // just search + + if (i < m_autospells.size()) + { + m_autospells.erase(itr2); + itr->second->active = ACT_DISABLED; + itr->second->state = PETSPELL_CHANGED; + } } } diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 519e28ad0..edf78f86c 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -3030,8 +3030,11 @@ void Aura::HandleModPossessPet(bool apply, bool Real) return; Unit* caster = GetCaster(); + if(!caster || caster->GetTypeId() != TYPEID_PLAYER) + return; + Pet *pet = caster->GetPet(); - if(!pet || (pet != m_target) || !caster || (caster->GetTypeId() != TYPEID_PLAYER)) + if(!pet || pet != m_target) return; if(apply) From cd44cfe79dc28be45178d51e98aa87e2a5df2606 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 10 Dec 2008 19:20:29 +0300 Subject: [PATCH 160/256] Drop commented code in VMapManager.cpp. --- src/shared/vmap/VMapManager.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/shared/vmap/VMapManager.cpp b/src/shared/vmap/VMapManager.cpp index a93f2a827..49fec68b5 100644 --- a/src/shared/vmap/VMapManager.cpp +++ b/src/shared/vmap/VMapManager.cpp @@ -275,11 +275,7 @@ namespace VMAP { dirFileName = getDirFileName(pMapId); } - //size_t len = pBasePath.length() + dirFileName.length(); - //char *filenameBuffer = new char[len+1]; - //sprintf(filenameBuffer, "%s%s", pBasePath.c_str(), dirFileName.c_str()); std::string fb = pBasePath + dirFileName; - //FILE* df = fopen(filenameBuffer, "rb"); FILE* df = fopen(fb.c_str(), "rb"); if(df) { @@ -290,11 +286,7 @@ namespace VMAP chomp(name); if(name.length() >1) { - //size_t len2 = pBasePath.length() + name.length(); - //char *filenameBuffer2 = new char[len2+1]; - //sprintf(filenameBuffer2, "%s%s", pBasePath.c_str(), name.c_str()); std::string fb2 = pBasePath + name; - //FILE* df2 = fopen(filenameBuffer2, "rb"); FILE* df2 = fopen(fb2.c_str(), "rb"); if(df2) { @@ -304,12 +296,10 @@ namespace VMAP result = true; fclose(df2); } - //delete[] filenameBuffer2; } } fclose(df); } - //delete[] filenameBuffer; return result; } @@ -666,15 +656,11 @@ namespace VMAP bool MapTree::loadMap(const std::string& pDirFileName, unsigned int pMapTileIdent) { bool result = true; - //size_t len = iBasePath.length() + pDirFileName.length(); - //char *filenameBuffer = new char[len+1]; if(!hasDirFile(pDirFileName)) { FilesInDir filesInDir; result = false; std::string fb = iBasePath + pDirFileName; - //sprintf(filenameBuffer, "%s%s", iBasePath.c_str(), pDirFileName.c_str()); - //FILE* df = fopen(filenameBuffer, "rb"); FILE* df = fopen(fb.c_str(), "rb"); if(df) { @@ -735,7 +721,6 @@ namespace VMAP filesInDir.incRefCount(); } } - //delete [] filenameBuffer; return (result); } From 0f7077546fa4eafe4a8b7d94e0ce8d5fbe9c3a03 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Fri, 12 Dec 2008 01:44:52 +0300 Subject: [PATCH 161/256] Implemented character customize future. Not tested, but should work... --- sql/wotlk_updates/10_mangos_string.sql | 3 + src/game/CharacterHandler.cpp | 120 +++++++++++++++++++++---- src/game/Chat.cpp | 1 + src/game/Chat.h | 1 + src/game/Language.h | 2 + src/game/Level2.cpp | 53 +++++++++++ src/game/Opcodes.cpp | 2 +- src/game/Player.cpp | 109 +++++++++++----------- src/game/Player.h | 4 +- src/game/WorldSession.h | 1 + src/shared/Database/DBCStructure.h | 5 +- 11 files changed, 229 insertions(+), 72 deletions(-) create mode 100644 sql/wotlk_updates/10_mangos_string.sql diff --git a/sql/wotlk_updates/10_mangos_string.sql b/sql/wotlk_updates/10_mangos_string.sql new file mode 100644 index 000000000..7ac51e307 --- /dev/null +++ b/sql/wotlk_updates/10_mangos_string.sql @@ -0,0 +1,3 @@ +INSERT INTO `mangos_string` VALUES +(345,'Forced customize for player %s will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(346,'Forced customize for player %s (GUID #%u) will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 6056832e4..f43fef017 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -914,7 +914,7 @@ void WorldSession::HandleToggleCloakOpcode( WorldPacket & /*recv_data*/ ) void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) { - CHECK_PACKET_SIZE(recv_data,8+1); + CHECK_PACKET_SIZE(recv_data, 8+1); uint64 guid; std::string newname; @@ -929,21 +929,20 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) if (!result) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_CREATE_ERROR; + data << uint8(CHAR_CREATE_ERROR); SendPacket( &data ); return; } - uint32 at_loginFlags; Field *fields = result->Fetch(); - at_loginFlags = fields[0].GetUInt32(); + uint32 at_loginFlags = fields[0].GetUInt32(); oldname = fields[1].GetCppString(); delete result; if (!(at_loginFlags & AT_LOGIN_RENAME)) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_CREATE_ERROR; + data << uint8(CHAR_CREATE_ERROR); SendPacket( &data ); return; } @@ -952,7 +951,7 @@ 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; } @@ -960,7 +959,7 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) 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; } @@ -969,7 +968,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; } @@ -977,7 +976,7 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) if(objmgr.GetPlayerGUIDByName(newname)) // character with this name already exist { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_CREATE_ERROR; + data << uint8(CHAR_CREATE_NAME_IN_USE); SendPacket( &data ); return; } @@ -985,23 +984,21 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) if(newname == oldname) // checked by client { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_NAME_FAILURE; + data << uint8(CHAR_NAME_FAILURE); SendPacket( &data ); return; } - // we have to check character at_login_flag & AT_LOGIN_RENAME also (fake packets hehe) - CharacterDatabase.escape_string(newname); - CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME),GUID_LOPART(guid)); + CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME), 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:[%s] (guid:%u) Changed name to: %s",GetAccountId(),IP_str.c_str(),oldname.c_str(),GUID_LOPART(guid),newname.c_str()); + sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s", GetAccountId(), IP_str.c_str(), oldname.c_str(), GUID_LOPART(guid), newname.c_str()); WorldPacket data(SMSG_CHAR_RENAME,1+8+(newname.size()+1)); - data << (uint8)RESPONSE_SUCCESS; - data << guid; + data << uint8(RESPONSE_SUCCESS); + data << uint64(guid); data << newname; SendPacket(&data); } @@ -1167,3 +1164,94 @@ void WorldSession::HandleRemoveGlyph( WorldPacket & recv_data ) } } } + +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 3dcf8dc96..531e28670 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -555,6 +555,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 }, diff --git a/src/game/Chat.h b/src/game/Chat.h index c31ae319c..f719d0aa8 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -406,6 +406,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); diff --git a/src/game/Language.h b/src/game/Language.h index ad5a2b43c..7b30279c9 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -326,6 +326,8 @@ enum MangosStrings 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 diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 875533ffc..6d4777800 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -3356,6 +3356,59 @@ bool ChatHandler::HandleRenameCommand(const char* args) 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 = px; + + if(!normalizePlayerName(oldname)) + { + 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, target->GetName()); + target->SetAtLoginFlag(AT_LOGIN_CUSTOMIZE); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '8' WHERE guid = '%u'", target->GetGUIDLow()); + } + else + { + PSendSysMessage(LANG_CUSTOMIZE_PLAYER_GUID, oldname.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) { diff --git a/src/game/Opcodes.cpp b/src/game/Opcodes.cpp index cde8c4df8..cc8131e7e 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -1165,7 +1165,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] = /*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_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 }, diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 8456e39db..f4c402646 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -1329,13 +1329,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); @@ -1350,14 +1352,15 @@ void Player::BuildEnumData( QueryResult * result, WorldPacket * p_data ) // 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()); 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)) @@ -1368,14 +1371,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 << (uint32)0; // new wotlk - *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 { @@ -1386,8 +1388,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(entry); if(cInfo) @@ -1398,36 +1398,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); @@ -1444,20 +1419,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() @@ -15791,6 +15766,36 @@ 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 player_bytes = atol(tokens[PLAYER_BYTES].c_str()); + ((uint8*)player_bytes)[0] = skin; + ((uint8*)player_bytes)[1] = face; + ((uint8*)player_bytes)[2] = hairStyle; + ((uint8*)player_bytes)[3] = hairColor; + char buf[11]; + snprintf(buf,11,"%u",player_bytes); + tokens[PLAYER_BYTES] = buf; + + uint32 player_bytes2 = atol(tokens[PLAYER_BYTES_2].c_str()); + ((uint8*)player_bytes2)[0] = facialHair; + char buf2[11]; + snprintf(buf2,11,"%u",player_bytes2); + tokens[PLAYER_BYTES_2] = buf; + + uint32 player_bytes3 = atol(tokens[PLAYER_BYTES_3].c_str()); + ((uint8*)player_bytes3)[0] = gender; + char buf3[11]; + snprintf(buf3,11,"%u",player_bytes3); + tokens[PLAYER_BYTES_3] = buf; + + SaveValuesArrayInDB(tokens,guid); +} + void Player::SendAttackSwingNotStanding() { WorldPacket data(SMSG_ATTACKSWING_NOTSTANDING, 0); diff --git a/src/game/Player.h b/src/game/Player.h index b302d64fc..82c4899c8 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -548,7 +548,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 QuestStatusMap; @@ -1333,6 +1334,7 @@ class MANGOS_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; diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 383bb8964..c12810a62 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -664,6 +664,7 @@ class MANGOS_DLL_SPEC WorldSession 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 diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 4f30eb11c..222266c96 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -40,7 +40,8 @@ struct AchievementEntry uint32 ID; // 0 uint32 factionFlag; // 1 -1=all, 0=horde, 1=alliance uint32 mapID; // 2 -1=none - //char *name[16]; // 3-19 + //uint32 unk; // 3 + //char *name[16]; // 4-19 //uint32 name_flags; // 20 //char *description[16]; // 21-36 //uint32 desc_flags; // 37 @@ -48,7 +49,7 @@ struct AchievementEntry uint32 points; // 39 reward points //uint32 OrderInCategory; // 40 uint32 flags; // 41 - //uint32 flags; // 42 not flags, some unknown value... + //uint32 icon; // 42 icon //char *unk1[16]; // 43-58 //uint32 unk_flags; // 59 //uint32 count; // 60 From 05eee70e5003ee7b7dbb0c8bc93a6247ef4292e5 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 12 Dec 2008 05:26:38 +0300 Subject: [PATCH 162/256] Update `player_classlevelstats` table for new levels and class. Data for warlocks 71-80 have only near to correct data instead exactly correct values. --- sql/mangos.sql | 172 ++++++++++++++++- .../11_mangos_player_classlevelstats.sql | 181 ++++++++++++++++++ 2 files changed, 352 insertions(+), 1 deletion(-) create mode 100644 sql/wotlk_updates/11_mangos_player_classlevelstats.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 7c5817f30..2909816f3 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -3444,6 +3444,16 @@ INSERT INTO `player_classlevelstats` VALUES (1,68,3774,0), (1,69,4109,0), (1,70,4444,0), +(1,71,4720,0), +(1,72,5013,0), +(1,73,5325,0), +(1,74,5656,0), +(1,75,6008,0), +(1,76,6381,0), +(1,77,6778,0), +(1,78,7198,0), +(1,79,7646,0), +(1,80,8121,0), (2,1,28,60), (2,2,36,78), (2,3,44,98), @@ -3514,6 +3524,16 @@ INSERT INTO `player_classlevelstats` VALUES (2,68,2901,2665), (2,69,3134,2809), (2,70,3377,2953), +(2,71,3629,3097), +(2,72,3900,3241), +(2,73,4191,3385), +(2,74,4503,3529), +(2,75,4839,3673), +(2,76,5200,3817), +(2,77,5588,3962), +(2,78,6005,4106), +(2,79,6453,4250), +(2,80,6934,4394), (3,1,46,65), (3,2,53,70), (3,3,60,76), @@ -3584,6 +3604,16 @@ INSERT INTO `player_classlevelstats` VALUES (3,68,3075,3050), (3,69,3316,3217), (3,70,3568,3383), +(3,71,3834,3549), +(3,72,4120,3716), +(3,73,4427,3882), +(3,74,4757,4048), +(3,75,5112,4215), +(3,76,5493,4381), +(3,77,5903,4547), +(3,78,6343,4713), +(3,79,6816,4880), +(3,80,7324,5046), (4,1,25,0), (4,2,32,0), (4,3,49,0), @@ -3654,6 +3684,16 @@ INSERT INTO `player_classlevelstats` VALUES (4,68,3190,0), (4,69,3450,0), (4,70,3704,0), +(4,71,3980,0), +(4,72,4277,0), +(4,73,4596,0), +(4,74,4939,0), +(4,75,5307,0), +(4,76,5703,0), +(4,77,6128,0), +(4,78,6585,0), +(4,79,7076,0), +(4,80,7604,0), (5,1,52,73), (5,2,57,76), (5,3,72,95), @@ -3724,6 +3764,96 @@ INSERT INTO `player_classlevelstats` VALUES (5,68,2936,2371), (5,69,3160,2495), (5,70,3391,2620), +(5,71,3644,2744), +(5,72,3916,2868), +(5,73,4208,2993), +(5,74,4522,3117), +(5,75,4859,3242), +(5,76,5221,3366), +(5,77,5610,3490), +(5,78,6028,3615), +(5,79,6477,3739), +(5,80,6960,3863), +(6,1,22,0), +(6,2,27,0), +(6,3,32,0), +(6,4,37,0), +(6,5,42,0), +(6,6,47,0), +(6,7,52,0), +(6,8,58,0), +(6,9,64,0), +(6,10,70,0), +(6,11,77,0), +(6,12,84,0), +(6,13,92,0), +(6,14,100,0), +(6,15,117,0), +(6,16,127,0), +(6,17,138,0), +(6,18,150,0), +(6,19,163,0), +(6,20,177,0), +(6,21,192,0), +(6,22,208,0), +(6,23,225,0), +(6,24,239,0), +(6,25,258,0), +(6,26,278,0), +(6,27,299,0), +(6,28,321,0), +(6,29,344,0), +(6,30,368,0), +(6,31,393,0), +(6,32,419,0), +(6,33,446,0), +(6,34,474,0), +(6,35,503,0), +(6,36,533,0), +(6,37,564,0), +(6,38,596,0), +(6,39,629,0), +(6,40,698,0), +(6,41,698,0), +(6,42,734,0), +(6,43,771,0), +(6,44,809,0), +(6,45,849,0), +(6,46,891,0), +(6,47,935,0), +(6,48,981,0), +(6,49,1029,0), +(6,50,1079,0), +(6,51,1131,0), +(6,52,1185,0), +(6,53,1241,0), +(6,54,1299,0), +(6,55,1359,0), +(6,56,1421,0), +(6,57,1485,0), +(6,58,1551,0), +(6,59,1619,0), +(6,60,1689,0), +(6,61,1902,0), +(6,62,2129,0), +(6,63,2357,0), +(6,64,2612,0), +(6,65,2883,0), +(6,66,3169,0), +(6,67,3455,0), +(6,68,3774,0), +(6,69,4109,0), +(6,70,4444,0), +(6,71,4720,0), +(6,72,5013,0), +(6,73,5325,0), +(6,74,5656,0), +(6,75,6008,0), +(6,76,6381,0), +(6,77,6778,0), +(6,78,7199,0), +(6,79,7646,0), +(6,80,8121,0), (7,1,37,85), (7,2,44,91), (7,3,51,98), @@ -3794,6 +3924,16 @@ INSERT INTO `player_classlevelstats` VALUES (7,68,2713,2670), (7,69,2931,2814), (7,70,3159,2958), +(7,71,3395,3102), +(7,72,3648,3246), +(7,73,3920,3389), +(7,74,4212,3533), +(7,75,4526,3677), +(7,76,4863,3821), +(7,77,5226,3965), +(7,78,5616,4108), +(7,79,6035,4252), +(7,80,6485,4396), (8,1,32,100), (8,2,47,110), (8,3,52,106), @@ -3864,6 +4004,16 @@ INSERT INTO `player_classlevelstats` VALUES (8,68,2906,2035), (8,69,3136,2138), (8,70,3393,2241), +(8,71,3646,2343), +(8,72,3918,2446), +(8,73,4210,2549), +(8,74,4524,2652), +(8,75,4861,2754), +(8,76,5223,2857), +(8,77,5612,2960), +(8,78,6030,3063), +(8,79,6480,3165), +(8,80,6963,3268), (9,1,23,90), (9,2,28,98), (9,3,43,107), @@ -3934,6 +4084,16 @@ INSERT INTO `player_classlevelstats` VALUES (9,68,2991,2366), (9,69,3235,2490), (9,70,3490,2615), +(9,71,3750,2739), +(9,72,4025,2863), +(9,73,4330,2987), +(9,74,4646,3111), +(9,75,4997,3235), +(9,76,5373,3360), +(9,77,5774,3483), +(9,78,6207,3608), +(9,79,6667,3732), +(9,80,7136,3856), (11,1,44,60), (11,2,51,66), (11,3,58,73), @@ -4003,7 +4163,17 @@ INSERT INTO `player_classlevelstats` VALUES (11,67,2872,2032), (11,68,3114,2145), (11,69,3351,2257), -(11,70,3614,2370); +(11,70,3614,2370), +(11,71,3883,2482), +(11,72,4172,2595), +(11,73,4483,2708), +(11,74,4817,2820), +(11,75,5176,2933), +(11,76,5562,3045), +(11,77,5977,3158), +(11,78,6423,3270), +(11,79,6902,3383), +(11,80,7417,3496); /*!40000 ALTER TABLE `player_classlevelstats` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/wotlk_updates/11_mangos_player_classlevelstats.sql b/sql/wotlk_updates/11_mangos_player_classlevelstats.sql new file mode 100644 index 000000000..6133ac0a0 --- /dev/null +++ b/sql/wotlk_updates/11_mangos_player_classlevelstats.sql @@ -0,0 +1,181 @@ +DELETE FROM `player_classlevelstats` WHERE class = 6 OR level > 70; +INSERT INTO `player_classlevelstats` VALUES +(1,71,4720,0), +(1,72,5013,0), +(1,73,5325,0), +(1,74,5656,0), +(1,75,6008,0), +(1,76,6381,0), +(1,77,6778,0), +(1,78,7198,0), +(1,79,7646,0), +(1,80,8121,0), + +(2,71,3629,3097), +(2,72,3900,3241), +(2,73,4191,3385), +(2,74,4503,3529), +(2,75,4839,3673), +(2,76,5200,3817), +(2,77,5588,3962), +(2,78,6005,4106), +(2,79,6453,4250), +(2,80,6934,4394), + +(3,71,3834,3549), +(3,72,4120,3716), +(3,73,4427,3882), +(3,74,4757,4048), +(3,75,5112,4215), +(3,76,5493,4381), +(3,77,5903,4547), +(3,78,6343,4713), +(3,79,6816,4880), +(3,80,7324,5046), + +(4,71,3980,0), +(4,72,4277,0), +(4,73,4596,0), +(4,74,4939,0), +(4,75,5307,0), +(4,76,5703,0), +(4,77,6128,0), +(4,78,6585,0), +(4,79,7076,0), +(4,80,7604,0), + +(5,71,3644,2744), +(5,72,3916,2868), +(5,73,4208,2993), +(5,74,4522,3117), +(5,75,4859,3242), +(5,76,5221,3366), +(5,77,5610,3490), +(5,78,6028,3615), +(5,79,6477,3739), +(5,80,6960,3863), + +(6,1,22,0), +(6,2,27,0), +(6,3,32,0), +(6,4,37,0), +(6,5,42,0), +(6,6,47,0), +(6,7,52,0), +(6,8,58,0), +(6,9,64,0), +(6,10,70,0), +(6,11,77,0), +(6,12,84,0), +(6,13,92,0), +(6,14,100,0), +(6,15,117,0), +(6,16,127,0), +(6,17,138,0), +(6,18,150,0), +(6,19,163,0), +(6,20,177,0), +(6,21,192,0), +(6,22,208,0), +(6,23,225,0), +(6,24,239,0), +(6,25,258,0), +(6,26,278,0), +(6,27,299,0), +(6,28,321,0), +(6,29,344,0), +(6,30,368,0), +(6,31,393,0), +(6,32,419,0), +(6,33,446,0), +(6,34,474,0), +(6,35,503,0), +(6,36,533,0), +(6,37,564,0), +(6,38,596,0), +(6,39,629,0), +(6,40,698,0), +(6,41,698,0), +(6,42,734,0), +(6,43,771,0), +(6,44,809,0), +(6,45,849,0), +(6,46,891,0), +(6,47,935,0), +(6,48,981,0), +(6,49,1029,0), +(6,50,1079,0), +(6,51,1131,0), +(6,52,1185,0), +(6,53,1241,0), +(6,54,1299,0), +(6,55,1359,0), +(6,56,1421,0), +(6,57,1485,0), +(6,58,1551,0), +(6,59,1619,0), +(6,60,1689,0), +(6,61,1902,0), +(6,62,2129,0), +(6,63,2357,0), +(6,64,2612,0), +(6,65,2883,0), +(6,66,3169,0), +(6,67,3455,0), +(6,68,3774,0), +(6,69,4109,0), +(6,70,4444,0), +(6,71,4720,0), +(6,72,5013,0), +(6,73,5325,0), +(6,74,5656,0), +(6,75,6008,0), +(6,76,6381,0), +(6,77,6778,0), +(6,78,7199,0), +(6,79,7646,0), +(6,80,8121,0), + +(7,71,3395,3102), +(7,72,3648,3246), +(7,73,3920,3389), +(7,74,4212,3533), +(7,75,4526,3677), +(7,76,4863,3821), +(7,77,5226,3965), +(7,78,5616,4108), +(7,79,6035,4252), +(7,80,6485,4396), + +(8,71,3646,2343), +(8,72,3918,2446), +(8,73,4210,2549), +(8,74,4524,2652), +(8,75,4861,2754), +(8,76,5223,2857), +(8,77,5612,2960), +(8,78,6030,3063), +(8,79,6480,3165), +(8,80,6963,3268), + +(9,71,3750,2739), +(9,72,4025,2863), +(9,73,4330,2987), +(9,74,4646,3111), +(9,75,4997,3235), +(9,76,5373,3360), +(9,77,5774,3483), +(9,78,6207,3608), +(9,79,6667,3732), +(9,80,7136,3856), + +(11,71,3883,2482), +(11,72,4172,2595), +(11,73,4483,2708), +(11,74,4817,2820), +(11,75,5176,2933), +(11,76,5562,3045), +(11,77,5977,3158), +(11,78,6423,3270), +(11,79,6902,3383), +(11,80,7417,3496); From 0f12997ef195ba1a2bab07fbb63999018be2d0b6 Mon Sep 17 00:00:00 2001 From: hunuza Date: Fri, 12 Dec 2008 14:16:24 +0100 Subject: [PATCH 163/256] [6899] Pass const reference instead of value for some strings in some functions. Signed-off-by: hunuza --- src/game/ArenaTeamHandler.cpp | 4 ++-- src/game/Channel.cpp | 4 ++-- src/game/Channel.h | 6 +++--- src/game/ChannelMgr.h | 8 ++++---- src/game/Chat.cpp | 2 +- src/game/Chat.h | 2 +- src/game/GMTicketMgr.h | 2 +- src/game/GossipDef.cpp | 6 +++--- src/game/GossipDef.h | 6 +++--- src/game/Guild.cpp | 6 +++--- src/game/Guild.h | 8 ++++---- src/game/GuildHandler.cpp | 2 +- src/game/Mail.cpp | 2 +- src/game/NPCHandler.cpp | 2 +- src/game/Object.h | 2 +- src/game/ObjectMgr.cpp | 16 ++++++++-------- src/game/ObjectMgr.h | 18 +++++++++--------- src/game/PetHandler.cpp | 2 +- src/game/Player.cpp | 14 +++++++------- src/game/Player.h | 14 +++++++------- src/game/PlayerDump.cpp | 4 ++-- src/game/PlayerDump.h | 4 ++-- src/game/SocialMgr.h | 2 +- src/game/World.cpp | 2 +- src/game/World.h | 2 +- src/game/WorldSession.h | 12 ++++++------ src/realmd/AuthSocket.cpp | 2 +- src/realmd/AuthSocket.h | 2 +- src/realmd/RealmList.cpp | 2 +- src/realmd/RealmList.h | 2 +- src/shared/Common.cpp | 2 +- src/shared/Common.h | 2 +- src/shared/Database/DBCStores.cpp | 6 +++--- src/shared/Database/DBCStores.h | 2 +- src/shared/Log.cpp | 2 +- src/shared/Log.h | 2 +- src/shared/Util.cpp | 14 +++++++------- src/shared/Util.h | 14 +++++++------- src/shared/revision_nr.h | 2 +- src/shared/vmap/CoordModelMapping.h | 10 +++++----- 40 files changed, 108 insertions(+), 108 deletions(-) diff --git a/src/game/ArenaTeamHandler.cpp b/src/game/ArenaTeamHandler.cpp index 7cab8d085..16784bbcb 100644 --- a/src/game/ArenaTeamHandler.cpp +++ b/src/game/ArenaTeamHandler.cpp @@ -360,7 +360,7 @@ void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data at->BroadcastPacket(&data); } -void WorldSession::SendArenaTeamCommandResult(uint32 unk1, std::string str1, std::string str2, uint32 unk3) +void WorldSession::SendArenaTeamCommandResult(uint32 unk1, const std::string& str1, const std::string& str2, uint32 unk3) { WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+str1.length()+1+str2.length()+1+4); data << unk1; @@ -370,7 +370,7 @@ void WorldSession::SendArenaTeamCommandResult(uint32 unk1, std::string str1, std SendPacket(&data); } -void WorldSession::BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, std::string str1, std::string str2, std::string str3) +void WorldSession::BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, const std::string& str1, const std::string& str2, const std::string& str3) { data->Initialize(SMSG_ARENA_TEAM_EVENT, 1+1+1); *data << eventid; diff --git a/src/game/Channel.cpp b/src/game/Channel.cpp index 2fb8b5d09..22c1a5b1a 100644 --- a/src/game/Channel.cpp +++ b/src/game/Channel.cpp @@ -21,7 +21,7 @@ #include "World.h" #include "SocialMgr.h" -Channel::Channel(std::string name, uint32 channel_id) +Channel::Channel(const std::string& name, uint32 channel_id) : m_name(name), m_announce(true), m_moderate(false), m_channelId(channel_id), m_ownerGUID(0), m_password(""), m_flags(0) { // set special flags if built-in channel @@ -773,7 +773,7 @@ void Channel::MakeOwnerChanged(WorldPacket *data, uint64 guid) } // done 0x09 -void Channel::MakePlayerNotFound(WorldPacket *data, std::string name) +void Channel::MakePlayerNotFound(WorldPacket *data, const std::string& name) { MakeNotifyPacket(data, CHAT_PLAYER_NOT_FOUND_NOTICE); *data << name; diff --git a/src/game/Channel.h b/src/game/Channel.h index fc87efdd0..c3214f824 100644 --- a/src/game/Channel.h +++ b/src/game/Channel.h @@ -170,7 +170,7 @@ class Channel void MakeNotModerator(WorldPacket *data); //? 0x06 void MakePasswordChanged(WorldPacket *data, uint64 guid); //+ 0x07 void MakeOwnerChanged(WorldPacket *data, uint64 guid); //? 0x08 - void MakePlayerNotFound(WorldPacket *data, std::string name); //+ 0x09 + void MakePlayerNotFound(WorldPacket *data, const std::string& name); //+ 0x09 void MakeNotOwner(WorldPacket *data); //? 0x0A void MakeChannelOwner(WorldPacket *data); //? 0x0B void MakeModeChange(WorldPacket *data, uint64 guid, uint8 oldflags); //+ 0x0C @@ -244,14 +244,14 @@ class Channel } public: - Channel(std::string name, uint32 channel_id); + Channel(const std::string& name, uint32 channel_id); std::string GetName() const { return m_name; } uint32 GetChannelId() const { return m_channelId; } bool IsConstant() const { return m_channelId != 0; } bool IsAnnounce() const { return m_announce; } bool IsLFG() const { return GetFlags() & CHANNEL_FLAG_LFG; } std::string GetPassword() const { return m_password; } - void SetPassword(std::string npassword) { m_password = npassword; } + void SetPassword(const std::string& npassword) { m_password = npassword; } void SetAnnounce(bool nannounce) { m_announce = nannounce; } uint32 GetNumPlayers() const { return players.size(); } uint8 GetFlags() const { return m_flags; } diff --git a/src/game/ChannelMgr.h b/src/game/ChannelMgr.h index b3e3ac2e4..124afec5c 100644 --- a/src/game/ChannelMgr.h +++ b/src/game/ChannelMgr.h @@ -36,7 +36,7 @@ class ChannelMgr delete itr->second; channels.clear(); } - Channel *GetJoinChannel(std::string name, uint32 channel_id) + Channel *GetJoinChannel(const std::string& name, uint32 channel_id) { if(channels.count(name) == 0) { @@ -45,7 +45,7 @@ class ChannelMgr } return channels[name]; } - Channel *GetChannel(std::string name, Player *p) + Channel *GetChannel(const std::string& name, Player *p) { ChannelMap::const_iterator i = channels.find(name); @@ -59,7 +59,7 @@ class ChannelMgr else return i->second; } - void LeftChannel(std::string name) + void LeftChannel(const std::string& name) { ChannelMap::const_iterator i = channels.find(name); @@ -76,7 +76,7 @@ class ChannelMgr } private: ChannelMap channels; - void MakeNotOnPacket(WorldPacket *data, std::string name) + void MakeNotOnPacket(WorldPacket *data, const std::string& name) { data->Initialize(SMSG_CHANNEL_NOTIFY, (1+10)); // we guess size (*data) << (uint8)0x05 << name; diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index aa2ad5a0b..3c21a28ca 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -706,7 +706,7 @@ void ChatHandler::PSendSysMessage(const char *format, ...) SendSysMessage(str); } -bool ChatHandler::ExecuteCommandInTable(ChatCommand *table, const char* text, std::string fullcmd) +bool ChatHandler::ExecuteCommandInTable(ChatCommand *table, const char* text, const std::string& fullcmd) { char const* oldtext = text; std::string cmd = ""; diff --git a/src/game/Chat.h b/src/game/Chat.h index 73e0d6d50..bd66f6877 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -80,7 +80,7 @@ class ChatHandler void SendGlobalSysMessage(const char *str); - bool ExecuteCommandInTable(ChatCommand *table, const char* text, std::string fullcommand); + bool ExecuteCommandInTable(ChatCommand *table, const char* text, const std::string& fullcommand); bool ShowHelpForCommand(ChatCommand *table, const char* cmd); bool ShowHelpForSubCommands(ChatCommand *table, char const* cmd, char const* subcmd); diff --git a/src/game/GMTicketMgr.h b/src/game/GMTicketMgr.h index 01e00874d..5f7bf69ea 100644 --- a/src/game/GMTicketMgr.h +++ b/src/game/GMTicketMgr.h @@ -31,7 +31,7 @@ class GMTicket { } - GMTicket(uint32 guid, std::string text, time_t update) : m_guid(guid), m_text(text), m_lastUpdate(update) + GMTicket(uint32 guid, const std::string& text, time_t update) : m_guid(guid), m_text(text), m_lastUpdate(update) { } diff --git a/src/game/GossipDef.cpp b/src/game/GossipDef.cpp index a690254e2..ed9ebb3e5 100644 --- a/src/game/GossipDef.cpp +++ b/src/game/GossipDef.cpp @@ -34,7 +34,7 @@ GossipMenu::~GossipMenu() ClearMenu(); } -void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, uint32 dtAction, std::string BoxMessage, uint32 BoxMoney, bool Coded) +void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, uint32 dtSender, uint32 dtAction, const std::string& BoxMessage, uint32 BoxMoney, bool Coded) { ASSERT( m_gItems.size() <= GOSSIP_MAX_MENU_ITEMS ); @@ -51,7 +51,7 @@ void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, u m_gItems.push_back(gItem); } -void GossipMenu::AddMenuItem(uint8 Icon, std::string Message, bool Coded) +void GossipMenu::AddMenuItem(uint8 Icon, const std::string& Message, bool Coded) { AddMenuItem( Icon, Message, 0, 0, "", 0, Coded); } @@ -341,7 +341,7 @@ void QuestMenu::ClearMenu() m_qItems.clear(); } -void PlayerMenu::SendQuestGiverQuestList( QEmote eEmote, std::string Title, uint64 npcGUID ) +void PlayerMenu::SendQuestGiverQuestList( QEmote eEmote, const std::string& Title, uint64 npcGUID ) { WorldPacket data( SMSG_QUESTGIVER_QUEST_LIST, 100 ); // guess size data << uint64(npcGUID); diff --git a/src/game/GossipDef.h b/src/game/GossipDef.h index ba5b36008..7cde0c3b1 100644 --- a/src/game/GossipDef.h +++ b/src/game/GossipDef.h @@ -101,8 +101,8 @@ class MANGOS_DLL_SPEC GossipMenu GossipMenu(); ~GossipMenu(); - void AddMenuItem(uint8 Icon, std::string Message, bool Coded = false); - void AddMenuItem(uint8 Icon, std::string Message, uint32 dtSender, uint32 dtAction, std::string BoxMessage, uint32 BoxMoney, bool Coded = false); + void AddMenuItem(uint8 Icon, const std::string& Message, bool Coded = false); + void AddMenuItem(uint8 Icon, const std::string& Message, uint32 dtSender, uint32 dtAction, const std::string& BoxMessage, uint32 BoxMoney, bool Coded = false); // for using from scripts, don't must be inlined void AddMenuItem(uint8 Icon, char const* Message, bool Coded = false); @@ -195,7 +195,7 @@ class MANGOS_DLL_SPEC PlayerMenu /*********************************************************/ void SendQuestGiverStatus( uint8 questStatus, uint64 npcGUID ); - void SendQuestGiverQuestList( QEmote eEmote, std::string Title, uint64 npcGUID ); + void SendQuestGiverQuestList( QEmote eEmote, const std::string& Title, uint64 npcGUID ); void SendQuestQueryResponse ( Quest const *pQuest ); void SendQuestGiverQuestDetails( Quest const *pQuest, uint64 npcGUID, bool ActivateAccept); diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index 19f6214b8..8076757b5 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -517,7 +517,7 @@ void Guild::SetOFFNOTE(uint64 guid,std::string offnote) CharacterDatabase.PExecute("UPDATE guild_member SET offnote = '%s' WHERE guid = '%u'", offnote.c_str(), itr->first); } -void Guild::BroadcastToGuild(WorldSession *session, std::string msg, uint32 language) +void Guild::BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language) { if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_GCHATSPEAK)) { @@ -534,7 +534,7 @@ void Guild::BroadcastToGuild(WorldSession *session, std::string msg, uint32 lang } } -void Guild::BroadcastToOfficers(WorldSession *session, std::string msg, uint32 language) +void Guild::BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language) { if (session && session->GetPlayer() && HasRankRight(session->GetPlayer()->GetRank(),GR_RIGHT_OFFCHATSPEAK)) { @@ -593,7 +593,7 @@ void Guild::CreateRank(std::string name_,uint32 rights) CharacterDatabase.PExecute( "INSERT INTO guild_rank (guildid,rid,rname,rights) VALUES ('%u', '%u', '%s', '%u')", Id, m_ranks.size(), name_.c_str(), rights ); } -void Guild::AddRank(std::string name_,uint32 rights, uint32 money) +void Guild::AddRank(const std::string& name_,uint32 rights, uint32 money) { m_ranks.push_back(RankInfo(name_,rights,money)); } diff --git a/src/game/Guild.h b/src/game/Guild.h index a97a8cfb0..952468a26 100644 --- a/src/game/Guild.h +++ b/src/game/Guild.h @@ -242,7 +242,7 @@ struct MemberSlot struct RankInfo { - RankInfo(std::string _name, uint32 _rights, uint32 _money) : name(_name), rights(_rights), BankMoneyPerDay(_money) + RankInfo(const std::string& _name, uint32 _rights, uint32 _money) : name(_name), rights(_rights), BankMoneyPerDay(_money) { for(uint8 i = 0; i < GUILD_BANK_MAX_TABS; ++i) { @@ -307,8 +307,8 @@ class Guild bool FillPlayerData(uint64 guid, MemberSlot* memslot); void LoadPlayerStatsByGuid(uint64 guid); - void BroadcastToGuild(WorldSession *session, std::string msg, uint32 language = LANG_UNIVERSAL); - void BroadcastToOfficers(WorldSession *session, std::string msg, uint32 language = LANG_UNIVERSAL); + void BroadcastToGuild(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL); + void BroadcastToOfficers(WorldSession *session, const std::string& msg, uint32 language = LANG_UNIVERSAL); void BroadcastPacketToRank(WorldPacket *packet, uint32 rankId); void BroadcastPacket(WorldPacket *packet); @@ -405,7 +405,7 @@ class Guild bool AddGBankItemToDB(uint32 GuildId, uint32 BankTab , uint32 BankTabSlot , uint32 GUIDLow, uint32 Entry ); protected: - void AddRank(std::string name,uint32 rights,uint32 money); + void AddRank(const std::string& name,uint32 rights,uint32 money); uint32 Id; std::string name; diff --git a/src/game/GuildHandler.cpp b/src/game/GuildHandler.cpp index d40bb9b4d..8b093b808 100644 --- a/src/game/GuildHandler.cpp +++ b/src/game/GuildHandler.cpp @@ -730,7 +730,7 @@ void WorldSession::HandleGuildDelRankOpcode(WorldPacket& /*recvPacket*/) guild->Roster(this); } -void WorldSession::SendGuildCommandResult(uint32 typecmd,std::string str,uint32 cmdresult) +void WorldSession::SendGuildCommandResult(uint32 typecmd, const std::string& str,uint32 cmdresult) { WorldPacket data(SMSG_GUILD_COMMAND_RESULT, (8+str.size()+1)); data << typecmd; diff --git a/src/game/Mail.cpp b/src/game/Mail.cpp index 06499d15b..24dbe1f09 100644 --- a/src/game/Mail.cpp +++ b/src/game/Mail.cpp @@ -352,7 +352,7 @@ void WorldSession::HandleReturnToSender(WorldPacket & recv_data ) pl->SendMailResult(mailId, MAIL_RETURNED_TO_SENDER, 0); } -void WorldSession::SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, std::string subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId ) +void WorldSession::SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, const std::string& subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId ) { if(messageType != MAIL_NORMAL) // return only to players { diff --git a/src/game/NPCHandler.cpp b/src/game/NPCHandler.cpp index 4303e1a6c..a54ce7628 100644 --- a/src/game/NPCHandler.cpp +++ b/src/game/NPCHandler.cpp @@ -114,7 +114,7 @@ void WorldSession::SendTrainerList( uint64 guid ) SendTrainerList( guid, str ); } -void WorldSession::SendTrainerList( uint64 guid,std::string strTitle ) +void WorldSession::SendTrainerList( uint64 guid, const std::string& strTitle ) { sLog.outDebug( "WORLD: SendTrainerList" ); diff --git a/src/game/Object.h b/src/game/Object.h index 16e1fbfdf..6abd05203 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -407,7 +407,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object InstanceData* GetInstanceData(); const char* GetName() const { return m_name.c_str(); } - void SetName(std::string newname) { m_name=newname; } + void SetName(const std::string& newname) { m_name=newname; } virtual const char* GetNameForLocaleIdx(int32 /*locale_idx*/) const { return GetName(); } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index a936c0cc2..3ac130ff2 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -199,7 +199,7 @@ Guild * ObjectMgr::GetGuildById(const uint32 GuildId) const return NULL; } -Guild * ObjectMgr::GetGuildByName(std::string guildname) const +Guild * ObjectMgr::GetGuildByName(const std::string& guildname) const { for(GuildSet::const_iterator itr = mGuildSet.begin(); itr != mGuildSet.end(); ++itr) if ((*itr)->GetName() == guildname) @@ -235,7 +235,7 @@ ArenaTeam* ObjectMgr::GetArenaTeamById(const uint32 ArenaTeamId) const return NULL; } -ArenaTeam* ObjectMgr::GetArenaTeamByName(std::string arenateamname) const +ArenaTeam* ObjectMgr::GetArenaTeamByName(const std::string& arenateamname) const { for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr) if ((*itr)->GetName() == arenateamname) @@ -1380,7 +1380,7 @@ uint32 ObjectMgr::GetPlayerAccountIdByGUID(const uint64 &guid) const return 0; } -uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(std::string name) const +uint32 ObjectMgr::GetPlayerAccountIdByPlayerName(const std::string& name) const { QueryResult *result = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'", name.c_str()); if(result) @@ -6135,7 +6135,7 @@ bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bo return false; } -bool ObjectMgr::IsValidName( std::string name, bool create ) +bool ObjectMgr::IsValidName( const std::string& name, bool create ) { std::wstring wname; if(!Utf8toWStr(name,wname)) @@ -6149,7 +6149,7 @@ bool ObjectMgr::IsValidName( std::string name, bool create ) return isValidString(wname,strictMask,false,create); } -bool ObjectMgr::IsValidCharterName( std::string name ) +bool ObjectMgr::IsValidCharterName( const std::string& name ) { std::wstring wname; if(!Utf8toWStr(name,wname)) @@ -6163,7 +6163,7 @@ bool ObjectMgr::IsValidCharterName( std::string name ) return isValidString(wname,strictMask,true); } -bool ObjectMgr::IsValidPetName( std::string name ) +bool ObjectMgr::IsValidPetName( const std::string& name ) { std::wstring wname; if(!Utf8toWStr(name,wname)) @@ -6792,7 +6792,7 @@ void ObjectMgr::LoadGameTele() sLog.outString( ">> Loaded %u game tele's", count ); } -GameTele const* ObjectMgr::GetGameTele(std::string name) const +GameTele const* ObjectMgr::GetGameTele(const std::string& name) const { // explicit name case std::wstring wname; @@ -6835,7 +6835,7 @@ bool ObjectMgr::AddGameTele(GameTele& tele) new_id,tele.position_x,tele.position_y,tele.position_z,tele.orientation,tele.mapId,tele.name.c_str()); } -bool ObjectMgr::DeleteGameTele(std::string name) +bool ObjectMgr::DeleteGameTele(const std::string& name) { // explicit name case std::wstring wname; diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index 1c408ce63..fa594e055 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -313,13 +313,13 @@ class ObjectMgr Guild* GetGuildByLeader(uint64 const&guid) const; Guild* GetGuildById(const uint32 GuildId) const; - Guild* GetGuildByName(std::string guildname) const; + Guild* GetGuildByName(const std::string& guildname) const; std::string GetGuildNameById(const uint32 GuildId) const; void AddGuild(Guild* guild) { mGuildSet.insert( guild ); } void RemoveGuild(Guild* guild) { mGuildSet.erase( guild ); } ArenaTeam* GetArenaTeamById(const uint32 ArenaTeamId) const; - ArenaTeam* GetArenaTeamByName(std::string ArenaTeamName) const; + ArenaTeam* GetArenaTeamByName(const std::string& ArenaTeamName) const; ArenaTeam* GetArenaTeamByCapitan(uint64 const& guid) const; void AddArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.insert( arenateam ); } void RemoveArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.erase( arenateam ); } @@ -405,7 +405,7 @@ class ObjectMgr bool GetPlayerNameByGUID(const uint64 &guid, std::string &name) const; uint32 GetPlayerTeamByGUID(const uint64 &guid) const; uint32 GetPlayerAccountIdByGUID(const uint64 &guid) const; - uint32 GetPlayerAccountIdByPlayerName(std::string name) const; + uint32 GetPlayerAccountIdByPlayerName(const std::string& name) const; uint32 GetNearestTaxiNode( float x, float y, float z, uint32 mapid ); void GetTaxiPath( uint32 source, uint32 destination, uint32 &path, uint32 &cost); @@ -698,15 +698,15 @@ class ObjectMgr // reserved names void LoadReservedPlayersNames(); - bool IsReservedName(std::string name) const + bool IsReservedName(const std::string& name) const { return m_ReservedNames.find(name) != m_ReservedNames.end(); } // name with valid structure and symbols - static bool IsValidName( std::string name, bool create = false ); - static bool IsValidCharterName( std::string name ); - static bool IsValidPetName( std::string name ); + static bool IsValidName( const std::string& name, bool create = false ); + static bool IsValidCharterName( const std::string& name ); + static bool IsValidPetName( const std::string& name ); static bool CheckDeclinedNames(std::wstring mainpart, DeclinedName const& names); @@ -730,10 +730,10 @@ class ObjectMgr if(itr==m_GameTeleMap.end()) return NULL; return &itr->second; } - GameTele const* GetGameTele(std::string name) const; + GameTele const* GetGameTele(const std::string& name) const; GameTeleMap const& GetGameTeleMap() const { return m_GameTeleMap; } bool AddGameTele(GameTele& data); - bool DeleteGameTele(std::string name); + bool DeleteGameTele(const std::string& name); CacheNpcOptionList const& GetNpcOptions() const { return m_mCacheNpcOptionList; } diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index eb51544d3..c1d21e131 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -668,7 +668,7 @@ void WorldSession::HandlePetCastSpellOpcode( WorldPacket& recvPacket ) } } -void WorldSession::SendPetNameInvalid(uint32 error, std::string name, DeclinedName *declinedName) +void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName) { WorldPacket data(SMSG_PET_NAME_INVALID, 4 + name.size() + 1 + 1); data << uint32(error); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 5a517f45d..277d9a341 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -182,7 +182,7 @@ void PlayerTaxi::AppendTaximaskTo( ByteBuffer& data, bool all ) } } -bool PlayerTaxi::LoadTaxiDestinationsFromString( std::string values ) +bool PlayerTaxi::LoadTaxiDestinationsFromString( const std::string& values ) { ClearTaxiDestinations(); @@ -476,7 +476,7 @@ void Player::CleanupsBeforeDelete() Unit::CleanupsBeforeDelete(); } -bool Player::Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId ) +bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId ) { //FIXME: outfitId not used in player creating @@ -15751,7 +15751,7 @@ void Player::Uncharm() charm->RemoveSpellsCausingAura(SPELL_AURA_MOD_POSSESS); } -void Player::BuildPlayerChat(WorldPacket *data, uint8 msgtype, std::string text, uint32 language) const +void Player::BuildPlayerChat(WorldPacket *data, uint8 msgtype, const std::string& text, uint32 language) const { *data << (uint8)msgtype; *data << (uint32)language; @@ -15763,28 +15763,28 @@ void Player::BuildPlayerChat(WorldPacket *data, uint8 msgtype, std::string text, *data << (uint8)chatTag(); } -void Player::Say(const std::string text, const uint32 language) +void Player::Say(const std::string& text, const uint32 language) { WorldPacket data(SMSG_MESSAGECHAT, 200); BuildPlayerChat(&data, CHAT_MSG_SAY, text, language); SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_SAY),true); } -void Player::Yell(const std::string text, const uint32 language) +void Player::Yell(const std::string& text, const uint32 language) { WorldPacket data(SMSG_MESSAGECHAT, 200); BuildPlayerChat(&data, CHAT_MSG_YELL, text, language); SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_YELL),true); } -void Player::TextEmote(const std::string text) +void Player::TextEmote(const std::string& text) { WorldPacket data(SMSG_MESSAGECHAT, 200); BuildPlayerChat(&data, CHAT_MSG_EMOTE, text, LANG_UNIVERSAL); SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true, !sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT) ); } -void Player::Whisper(std::string text, uint32 language,uint64 receiver) +void Player::Whisper(const std::string& text, uint32 language,uint64 receiver) { if (language != LANG_ADDON) // if not addon data language = LANG_UNIVERSAL; // whispers should always be readable diff --git a/src/game/Player.h b/src/game/Player.h index bc7e3d39c..89bc27b99 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -859,7 +859,7 @@ class MANGOS_DLL_SPEC PlayerTaxi void AppendTaximaskTo(ByteBuffer& data,bool all); // Destinations - bool LoadTaxiDestinationsFromString(std::string values); + bool LoadTaxiDestinationsFromString(const std::string& values); std::string SaveTaxiDestinationsToString(); void ClearTaxiDestinations() { m_TaxiDestinations.clear(); } @@ -912,7 +912,7 @@ class MANGOS_DLL_SPEC Player : public Unit } void SummonIfPossible(bool agree); - bool Create( uint32 guidlow, std::string name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId ); + bool Create( uint32 guidlow, const std::string& name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 outfitId ); void Update( uint32 time ); @@ -1004,11 +1004,11 @@ class MANGOS_DLL_SPEC Player : public Unit GuardianPetList const& GetGuardians() const { return m_guardianPets; } void Uncharm(); - void Say(std::string text, const uint32 language); - void Yell(std::string text, const uint32 language); - void TextEmote(std::string text); - void Whisper(std::string text, const uint32 language,uint64 receiver); - void BuildPlayerChat(WorldPacket *data, uint8 msgtype, std::string text, uint32 language) const; + void Say(const std::string& text, const uint32 language); + void Yell(const std::string& text, const uint32 language); + void TextEmote(const std::string& text); + void Whisper(const std::string& text, const uint32 language,uint64 receiver); + void BuildPlayerChat(WorldPacket *data, uint8 msgtype, const std::string& text, uint32 language) const; /*********************************************************/ /*** STORAGE SYSTEM ***/ diff --git a/src/game/PlayerDump.cpp b/src/game/PlayerDump.cpp index b7e66c968..b533cab6c 100644 --- a/src/game/PlayerDump.cpp +++ b/src/game/PlayerDump.cpp @@ -337,7 +337,7 @@ std::string PlayerDumpWriter::GetDump(uint32 guid) return dump; } -DumpReturn PlayerDumpWriter::WriteDump(std::string file, uint32 guid) +DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, uint32 guid) { FILE *fout = fopen(file.c_str(), "w"); if (!fout) @@ -353,7 +353,7 @@ DumpReturn PlayerDumpWriter::WriteDump(std::string file, uint32 guid) // Reading - High-level functions #define ROLLBACK(DR) {CharacterDatabase.RollbackTransaction(); fclose(fin); return (DR);} -DumpReturn PlayerDumpReader::LoadDump(std::string file, uint32 account, std::string name, uint32 guid) +DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid) { // check character count { diff --git a/src/game/PlayerDump.h b/src/game/PlayerDump.h index 2e83102f9..5991b7445 100644 --- a/src/game/PlayerDump.h +++ b/src/game/PlayerDump.h @@ -92,7 +92,7 @@ class PlayerDumpWriter : public PlayerDump PlayerDumpWriter() {} std::string GetDump(uint32 guid); - DumpReturn WriteDump(std::string file, uint32 guid); + DumpReturn WriteDump(const std::string& file, uint32 guid); private: typedef std::set GUIDs; @@ -111,7 +111,7 @@ class PlayerDumpReader : public PlayerDump public: PlayerDumpReader() {} - DumpReturn LoadDump(std::string file, uint32 account, std::string name, uint32 guid); + DumpReturn LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid); }; #endif diff --git a/src/game/SocialMgr.h b/src/game/SocialMgr.h index 8c873d8a0..0a7f822a7 100644 --- a/src/game/SocialMgr.h +++ b/src/game/SocialMgr.h @@ -63,7 +63,7 @@ struct FriendInfo Note = ""; } - FriendInfo(uint32 flags, std::string note) + FriendInfo(uint32 flags, const std::string& note) { Status = FRIEND_STATUS_OFFLINE; Flags = flags; diff --git a/src/game/World.cpp b/src/game/World.cpp index 2c2e87a3d..f66846362 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -2281,7 +2281,7 @@ void World::KickAllLess(AccountTypes sec) } /// Kick (and save) the designated player -bool World::KickPlayer(std::string playerName) +bool World::KickPlayer(const std::string& playerName) { SessionMap::iterator itr; diff --git a/src/game/World.h b/src/game/World.h index 2f3c0be57..d5b313503 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -438,7 +438,7 @@ class World bool IsPvPRealm() { return (getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP || getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP); } bool IsFFAPvPRealm() { return getConfig(CONFIG_GAME_TYPE) == REALM_TYPE_FFA_PVP; } - bool KickPlayer(std::string playerName); + bool KickPlayer(const std::string& playerName); void KickAll(); void KickAllLess(AccountTypes sec); BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author); diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 6077d42b4..34a626d80 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -81,7 +81,7 @@ class MANGOS_DLL_SPEC WorldSession void SendPacket(WorldPacket const* packet); void SendNotification(const char *format,...) ATTR_PRINTF(2,3); void SendNotification(int32 string_id,...); - void SendPetNameInvalid(uint32 error, std::string name, DeclinedName *declinedName); + void SendPetNameInvalid(uint32 error, const std::string& name, DeclinedName *declinedName); void SendLfgResult(uint32 type, uint32 entry, uint8 lfg_type); void SendPartyResult(PartyOperation operation, const std::string& member, PartyResult res); void SendAreaTriggerMessage(const char* Text, ...) ATTR_PRINTF(2,3); @@ -128,7 +128,7 @@ class MANGOS_DLL_SPEC WorldSession static void SendNameQueryOpcodeFromDBCallBack(QueryResult *result, uint32 accountId); void SendTrainerList( uint64 guid ); - void SendTrainerList( uint64 guid,std::string strTitle ); + void SendTrainerList( uint64 guid, const std::string& strTitle ); void SendListInventory( uint64 guid ); void SendShowBank( uint64 guid ); void SendTabardVendorActivate( uint64 guid ); @@ -153,7 +153,7 @@ class MANGOS_DLL_SPEC WorldSession //mail //used with item_page table bool SendItemInfo( uint32 itemid, WorldPacket data ); - static void SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, std::string subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId = 0); + static void SendReturnToSender(uint8 messageType, uint32 sender_acc, uint32 sender_guid, uint32 receiver_guid, const std::string& subject, uint32 itemTextId, MailItemsInfo *mi, uint32 money, uint16 mailTemplateId = 0); static void SendMailTo(Player* receiver, uint8 messageType, uint8 stationery, uint32 sender_guidlow_or_entry, uint32 received_guidlow, std::string subject, uint32 itemTextId, MailItemsInfo* mi, uint32 money, uint32 COD, uint32 checked, uint32 deliver_delay = 0, uint16 mailTemplateId = 0); //auction @@ -176,9 +176,9 @@ class MANGOS_DLL_SPEC WorldSession bool SendLearnNewTaxiNode( Creature* unit ); // Guild/Arena Team - void SendGuildCommandResult(uint32 typecmd,std::string str,uint32 cmdresult); - void SendArenaTeamCommandResult(uint32 unk1, std::string str1, std::string str2, uint32 unk3); - void BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, std::string str1, std::string str2, std::string str3); + void SendGuildCommandResult(uint32 typecmd, const std::string& str, uint32 cmdresult); + void SendArenaTeamCommandResult(uint32 unk1, const std::string& str1, const std::string& str2, uint32 unk3); + void BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, const std::string& str1, const std::string& str2, const std::string& str3); void SendNotInArenaTeamPacket(uint8 type); void SendPetitionShowList( uint64 guid ); void SendSaveGuildEmblem( uint32 msg ); diff --git a/src/realmd/AuthSocket.cpp b/src/realmd/AuthSocket.cpp index 987e1d210..e1759e7e0 100644 --- a/src/realmd/AuthSocket.cpp +++ b/src/realmd/AuthSocket.cpp @@ -298,7 +298,7 @@ void AuthSocket::OnRead() } /// Make the SRP6 calculation from hash in dB -void AuthSocket::_SetVSFields(std::string rI) +void AuthSocket::_SetVSFields(const std::string& rI) { BigNumber I; I.SetHexStr(rI.c_str()); diff --git a/src/realmd/AuthSocket.h b/src/realmd/AuthSocket.h index b46e1d425..0ed37587b 100644 --- a/src/realmd/AuthSocket.h +++ b/src/realmd/AuthSocket.h @@ -56,7 +56,7 @@ class AuthSocket: public TcpSocket bool _HandleXferCancel(); bool _HandleXferAccept(); - void _SetVSFields(std::string rI); + void _SetVSFields(const std::string& rI); FILE *pPatch; ZThread::Mutex patcherLock; diff --git a/src/realmd/RealmList.cpp b/src/realmd/RealmList.cpp index 7f4dd3e15..a25e495b0 100644 --- a/src/realmd/RealmList.cpp +++ b/src/realmd/RealmList.cpp @@ -42,7 +42,7 @@ void RealmList::Initialize(uint32 updateInterval) UpdateRealms(true); } -void RealmList::UpdateRealm( uint32 ID, std::string name, std::string address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu) +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]; diff --git a/src/realmd/RealmList.h b/src/realmd/RealmList.h index 15095e8fa..f3e04c07d 100644 --- a/src/realmd/RealmList.h +++ b/src/realmd/RealmList.h @@ -56,7 +56,7 @@ class RealmList uint32 size() const { return m_realms.size(); } private: void UpdateRealms(bool init); - void UpdateRealm( uint32 ID, std::string name, std::string address, uint32 port, uint8 icon, uint8 color, uint8 timezone, AccountTypes allowedSecurityLevel, float popu); + 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; diff --git a/src/shared/Common.cpp b/src/shared/Common.cpp index 952997d3b..e7224bc5e 100644 --- a/src/shared/Common.cpp +++ b/src/shared/Common.cpp @@ -30,7 +30,7 @@ char const* localeNames[MAX_LOCALE] = { "ruRU" }; -LocaleConstant GetLocaleByName(std::string name) +LocaleConstant GetLocaleByName(const std::string& name) { for(uint32 i = 0; i < MAX_LOCALE; ++i) if(name==localeNames[i]) diff --git a/src/shared/Common.h b/src/shared/Common.h index 5c938ea67..0fc544fc6 100644 --- a/src/shared/Common.h +++ b/src/shared/Common.h @@ -186,7 +186,7 @@ enum LocaleConstant extern char const* localeNames[MAX_LOCALE]; -LocaleConstant GetLocaleByName(std::string name); +LocaleConstant GetLocaleByName(const std::string& name); // we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some pother platforms) #ifdef max diff --git a/src/shared/Database/DBCStores.cpp b/src/shared/Database/DBCStores.cpp index e733551d2..1385f089f 100644 --- a/src/shared/Database/DBCStores.cpp +++ b/src/shared/Database/DBCStores.cpp @@ -128,7 +128,7 @@ DBCStorage sWorldSafeLocsStore(WorldSafeLocsEntryfmt); typedef std::list StoreProblemList; -static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, std::string filename) +static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, const std::string& filename) { sLog.outError("ERROR: Size of '%s' setted by format string (%u) not equal size of C++ structure (%u).",filename.c_str(),fsize,rsize); @@ -137,7 +137,7 @@ static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, std::string filename } template -inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList& errlist, DBCStorage& storage, std::string dbc_path, std::string filename) +inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList& errlist, DBCStorage& storage, const std::string& dbc_path, const std::string& filename) { // compatibility format and C++ structure sizes assert(DBCFile::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDBC_assert_print(DBCFile::GetFormatRecordSize(storage.GetFormat()),sizeof(T),filename)); @@ -172,7 +172,7 @@ inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList } } -void LoadDBCStores(std::string dataPath) +void LoadDBCStores(const std::string& dataPath) { std::string dbcPath = dataPath+"dbc/"; diff --git a/src/shared/Database/DBCStores.h b/src/shared/Database/DBCStores.h index 7811286c0..f71888d91 100644 --- a/src/shared/Database/DBCStores.h +++ b/src/shared/Database/DBCStores.h @@ -195,7 +195,7 @@ extern DBCStorage sTotemCategoryStore; //extern DBCStorage sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates extern DBCStorage sWorldSafeLocsStore; -void LoadDBCStores(std::string dataPath); +void LoadDBCStores(const std::string& dataPath); // script support functions MANGOS_DLL_SPEC DBCStorage const* GetSoundEntriesStore(); diff --git a/src/shared/Log.cpp b/src/shared/Log.cpp index ada02e62b..f5d05139b 100644 --- a/src/shared/Log.cpp +++ b/src/shared/Log.cpp @@ -43,7 +43,7 @@ Log::Log() : Initialize(); } -void Log::InitColors(std::string str) +void Log::InitColors(const std::string& str) { if(str.empty()) { diff --git a/src/shared/Log.h b/src/shared/Log.h index 2a4bb97e8..391a93d86 100644 --- a/src/shared/Log.h +++ b/src/shared/Log.h @@ -82,7 +82,7 @@ class Log : public MaNGOS::Singleton iMainFiles; G3D::Array iSingeFiles; - void appendToMain(std::string pStr) { iMainFiles.append(pStr); } - void appendToSingle(std::string pStr) { iSingeFiles.append(pStr); } + void appendToMain(const std::string& pStr) { iMainFiles.append(pStr); } + void appendToSingle(const std::string& pStr) { iSingeFiles.append(pStr); } size_t size() { return (iMainFiles.size() + iSingeFiles.size()); } }; @@ -113,7 +113,7 @@ namespace VMAP const NameCollection getFilenamesForCoordinate(unsigned int pMapId, int xPos, int yPos); - static unsigned int getMapIdFromFilename(std::string pName) + static unsigned int getMapIdFromFilename(const std::string& pName) { size_t spos; @@ -126,8 +126,8 @@ namespace VMAP } const G3D::Array& getMaps() const { return iMapIds; } - bool isAlreadyProcessedSingleFile(std::string pName) const { return iProcesseSingleFiles.containsKey(pName); } - void addAlreadyProcessedSingleFile(std::string pName) { iProcesseSingleFiles.set(pName,pName); } + bool isAlreadyProcessedSingleFile(const std::string& pName) const { return iProcesseSingleFiles.containsKey(pName); } + void addAlreadyProcessedSingleFile(const std::string& pName) { iProcesseSingleFiles.set(pName,pName); } inline void addWorldAreaMap(unsigned int pMapId) { From e3c093a3abd502cac93f01c2cb1a9c160a84421f Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 12 Dec 2008 16:35:15 +0300 Subject: [PATCH 164/256] [6900] Remove unneed include dependence. --- src/shared/Config/ConfigEnv.h | 1 - src/shared/revision_nr.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/shared/Config/ConfigEnv.h b/src/shared/Config/ConfigEnv.h index f2a0d5146..6c61aeb93 100644 --- a/src/shared/Config/ConfigEnv.h +++ b/src/shared/Config/ConfigEnv.h @@ -23,6 +23,5 @@ #include "Common.h" #include "dotconfpp/dotconfpp.h" #include "Config.h" -#include "Log.h" #endif diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a0a977003..756b9db72 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6899" + #define REVISION_NR "6900" #endif // __REVISION_NR_H__ From 027a3ab0bca27e20650dbf155b752800316109aa Mon Sep 17 00:00:00 2001 From: arrai Date: Fri, 12 Dec 2008 14:41:06 +0100 Subject: [PATCH 165/256] [6901] Fixed uninitialized variables --- src/game/Player.cpp | 1 + src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 277d9a341..3b5494057 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -13484,6 +13484,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) 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 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 756b9db72..268a993c6 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6900" + #define REVISION_NR "6901" #endif // __REVISION_NR_H__ From d8be07eabc9becc1801d1ba04d7d83b56a670c6d Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Fri, 12 Dec 2008 15:45:02 +0200 Subject: [PATCH 166/256] [6902] Fixed a bug in GetScriptId related to missing script names. --- src/game/ObjectMgr.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 3ac130ff2..1fbdf62c8 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -7243,7 +7243,7 @@ uint32 ObjectMgr::GetScriptId(const char *name) if(!name) return 0; ScriptNameMap::const_iterator itr = std::lower_bound(m_scriptNames.begin(), m_scriptNames.end(), name); - if(itr == m_scriptNames.end()) return 0; + if(itr == m_scriptNames.end() || *itr != name) return 0; return itr - m_scriptNames.begin(); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 268a993c6..f3c8a6fdf 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6901" + #define REVISION_NR "6902" #endif // __REVISION_NR_H__ From 857e7ae7eeaa6a4a846215c788a769af0ea88633 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Fri, 12 Dec 2008 18:09:30 +0300 Subject: [PATCH 167/256] Updated opcodes enum. --- src/game/CalendarHandler.cpp | 6 +- src/game/Opcodes.cpp | 2379 ++++++++++++++-------------- src/game/Opcodes.h | 37 +- src/game/Pet.cpp | 2 +- src/game/Player.cpp | 2 +- src/game/SpellAuras.cpp | 2 +- src/game/WorldSession.h | 2 +- src/realmd/AuthCodes.h | 4 +- src/shared/Database/DBCStructure.h | 7 +- 9 files changed, 1222 insertions(+), 1219 deletions(-) diff --git a/src/game/CalendarHandler.cpp b/src/game/CalendarHandler.cpp index a2a30b72a..9c69e3a91 100644 --- a/src/game/CalendarHandler.cpp +++ b/src/game/CalendarHandler.cpp @@ -107,12 +107,12 @@ void WorldSession::HandleCalendarComplain(WorldPacket &recv_data) recv_data.hexlike(); } -void WorldSession::HandleCalendarPendingInvites(WorldPacket &recv_data) +void WorldSession::HandleCalendarGetNumPending(WorldPacket &recv_data) { - sLog.outDebug("WORLD: CMSG_CALENDAR_PENDING_INVITES"); + sLog.outDebug("WORLD: CMSG_CALENDAR_GET_NUM_PENDING"); recv_data.hexlike(); - WorldPacket data(SMSG_CALENDAR_PENDING_INVITES, 4); + 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/Opcodes.cpp b/src/game/Opcodes.cpp index cc8131e7e..37f1bd344 100644 --- a/src/game/Opcodes.cpp +++ b/src/game/Opcodes.cpp @@ -26,1193 +26,1194 @@ /// 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_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*/ { "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::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::HandleGMTicketUpdateTextOpcode }, - /*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_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::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_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*/ { "MSG_GM_CHANGE_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*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_PENDING_INVITES", STATUS_LOGGEDIN, &WorldSession::HandleCalendarPendingInvites }, - /*0x448*/ { "SMSG_CALENDAR_PENDING_INVITES", 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_NEVER, &WorldSession::Handle_NULL }, - /*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_UNLEARNED_SPELL", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x49B*/ { "CMSG_MOVE_UNKNOWN_1179", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x49C*/ { "CMSG_UNKNOWN_1180", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x49D*/ { "SMSG_SHOW_VEHICLE_UI", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x49E*/ { "SMSG_CRITERIA_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x49F*/ { "SMSG_ACHIEVEMENT_REMOVE", STATUS_NEVER, &WorldSession::Handle_ServerSide }, - /*0x4A0*/ { "UMSG_UNKNOWN_1184", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4A1*/ { "UMSG_UNKNOWN_1185", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4A2*/ { "UMSG_UNKNOWN_1186", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4A3*/ { "UMSG_UNKNOWN_1187", STATUS_NEVER, &WorldSession::Handle_NULL }, - /*0x4A4*/ { "UMSG_UNKNOWN_1188", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*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::HandleGMTicketUpdateTextOpcode }, + /*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_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*/ { "MSG_GM_CHANGE_ARENA_RATING", STATUS_NEVER, &WorldSession::Handle_NULL }, + /*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_NEVER, &WorldSession::Handle_NULL }, + /*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 }, }; diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 83f33d0f2..7ea983757 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -366,7 +366,7 @@ enum Opcodes 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, @@ -725,8 +725,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, @@ -1123,8 +1123,8 @@ enum Opcodes SMSG_CALENDAR_EVENT_UPDATED_ALERT = 0x444, SMSG_CALENDAR_EVENT_MODERATOR_STATUS_ALERT = 0x445, CMSG_CALENDAR_COMPLAIN = 0x446, - CMSG_CALENDAR_PENDING_INVITES = 0x447, - SMSG_CALENDAR_PENDING_INVITES = 0x448, + CMSG_CALENDAR_GET_NUM_PENDING = 0x447, + SMSG_CALENDAR_SEND_NUM_PENDING = 0x448, CMSG_SAVE_DANCE = 0x449, SMSG_NOTIFY_DANCE = 0x44A, CMSG_PLAY_DANCE = 0x44B, @@ -1205,19 +1205,20 @@ enum Opcodes SMSG_AURA_UPDATE = 0x496, CMSG_FLOOD_GRACE_CHEAT = 0x497, SMSG_SERVER_FIRST_ACHIEVEMENT = 0x498, - SMSG_PET_LEARNED_SPELL = 0x499, // uint16 spellid, Your pet learned spell: %s - SMSG_PET_UNLEARNED_SPELL = 0x49A, // uint16 spellid, Your pet unlearned %s - CMSG_MOVE_UNKNOWN_1179 = 0x49B, // movement opcode - CMSG_UNKNOWN_1180 = 0x49C, // LUA: HearthAndResurrectFromArea - SMSG_SHOW_VEHICLE_UI = 0x49D, // empty - SMSG_CRITERIA_REMOVE = 0x49E, // uint32, broadcasts EVENT_CRITERIA_UPDATE - SMSG_ACHIEVEMENT_REMOVE = 0x49F, // uint32, broadcasts EVENT_ACHIEVEMENT_EARNED - UMSG_UNKNOWN_1184 = 0x4A0, // not found in client - UMSG_UNKNOWN_1185 = 0x4A1, // not found in client - UMSG_UNKNOWN_1186 = 0x4A2, // not found in client - UMSG_UNKNOWN_1187 = 0x4A3, // not found in client - UMSG_UNKNOWN_1188 = 0x4A4, // not found in client - NUM_MSG_TYPES = 0x4A5 + 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, + NUM_MSG_TYPES = 0x4A6 }; /// Player state diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 2dbdd5dc8..be46cc21a 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -1387,7 +1387,7 @@ bool Pet::unlearnSpell(uint16 spell_id) { if(!m_loading) { - WorldPacket data(SMSG_PET_UNLEARNED_SPELL, 2); + WorldPacket data(SMSG_PET_REMOVED_SPELL, 2); data << uint16(spell_id); ((Player*)GetOwner())->GetSession()->SendPacket(&data); } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index f4c402646..d07bfe94e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18758,7 +18758,7 @@ void Player::EnterVehicle(Vehicle *vehicle) SetClientControl(vehicle, 1); // redirect controls to vehicle - WorldPacket data(SMSG_SHOW_VEHICLE_UI, 0); // shows vehicle UI? + WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); GetSession()->SendPacket(&data); data.Initialize(MSG_MOVE_TELEPORT_ACK, 30); diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index edf78f86c..9340ded48 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -6409,7 +6409,7 @@ void Aura::HandleAuraControlVehicle(bool apply, bool Real) if(Pet *pet = m_target->GetPet()) pet->Remove(PET_SAVE_AS_CURRENT); - WorldPacket data(SMSG_SHOW_VEHICLE_UI, 0); + WorldPacket data(SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA, 0); ((Player*)m_target)->GetSession()->SendPacket(&data); } diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index c12810a62..be0045224 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -659,7 +659,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleCalendarEventStatus(WorldPacket& recv_data); void HandleCalendarEventModeratorStatus(WorldPacket& recv_data); void HandleCalendarComplain(WorldPacket& recv_data); - void HandleCalendarPendingInvites(WorldPacket& recv_data); + void HandleCalendarGetNumPending(WorldPacket& recv_data); void HandleSpellClick(WorldPacket& recv_data); void HandleAlterAppearance(WorldPacket& recv_data); diff --git a/src/realmd/AuthCodes.h b/src/realmd/AuthCodes.h index 53e77ee18..19ea32071 100644 --- a/src/realmd/AuthCodes.h +++ b/src/realmd/AuthCodes.h @@ -66,8 +66,8 @@ enum LoginResult // 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 and WoW:TBC 3.0.3 client build 9155, 9174, 9183... +// will only support WoW and WoW:TBC 3.0.3 client build 9155, 9174, 9183, 9328... -#define EXPECTED_MANGOS_CLIENT_BUILD {9155, 9174, 9183, 0} +#define EXPECTED_MANGOS_CLIENT_BUILD {9155, 9174, 9183, 9328, 0} #endif diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 222266c96..8cc274bb1 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -40,7 +40,7 @@ struct AchievementEntry uint32 ID; // 0 uint32 factionFlag; // 1 -1=all, 0=horde, 1=alliance uint32 mapID; // 2 -1=none - //uint32 unk; // 3 + //uint32 unk; // 3 parent achievement (previous, required) //char *name[16]; // 4-19 //uint32 name_flags; // 20 //char *description[16]; // 21-36 @@ -53,7 +53,7 @@ struct AchievementEntry //char *unk1[16]; // 43-58 //uint32 unk_flags; // 59 //uint32 count; // 60 - uint32 refAchievement; // 61 + uint32 refAchievement; // 61 related achievement? }; struct AchievementCategoryEntry @@ -459,8 +459,9 @@ struct AchievementCriteriaEntry //uint32 name_flags; // 25 uint32 completionFlag; // 26 uint32 groupFlag; // 27 + //uint32 unk1; // 28 uint32 timeLimit; // 29 time limit in seconds - //uint32 unk1; // 30 + //uint32 order; // 30 order }; struct AreaTableEntry From 3b753b830ba09646becd6724dc485cf31e83e171 Mon Sep 17 00:00:00 2001 From: Neo2003 Date: Fri, 12 Dec 2008 20:26:27 +0100 Subject: [PATCH 168/256] Allow creature equipments to use item.dbc entries since it's enough This will no more allow custom items to be equiped by creatures. Btw, since it uses client data to display them, it would not work. Signed-off-by: Neo2003 --- src/game/ObjectMgr.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 5e934a44d..98dcc0d15 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -944,24 +944,24 @@ void ObjectMgr::LoadEquipmentTemplates() if(!eqInfo->equipentry[j]) continue; - ItemPrototype const* proto = objmgr.GetItemPrototype(eqInfo->equipentry[j]); + ItemEntry const *dbcitem = sItemStore.LookupEntry(eqInfo->equipentry[j]); - if(!proto) + 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(eqInfo)->equipentry[j] = 0; continue; } - if(proto->InventoryType != INVTYPE_WEAPON && - proto->InventoryType != INVTYPE_SHIELD && - proto->InventoryType != INVTYPE_RANGED && - proto->InventoryType != INVTYPE_2HWEAPON && - proto->InventoryType != INVTYPE_WEAPONMAINHAND && - proto->InventoryType != INVTYPE_WEAPONOFFHAND && - proto->InventoryType != INVTYPE_HOLDABLE && - proto->InventoryType != INVTYPE_THROWN && - proto->InventoryType != INVTYPE_RANGEDRIGHT) + 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(eqInfo)->equipentry[j] = 0; @@ -970,6 +970,9 @@ void ObjectMgr::LoadEquipmentTemplates() } 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) @@ -1875,9 +1878,6 @@ void ObjectMgr::LoadItemPrototypes() const_cast(proto)->FoodType = 0; } } - - // this DBC used currently only for check item templates in DB. - sItemStore.Clear(); } void ObjectMgr::LoadAuctionItems() From d9de56ed2c989b1fdacbfa7c2f7493ff8d0bbbe7 Mon Sep 17 00:00:00 2001 From: hunuza Date: Fri, 12 Dec 2008 22:50:57 +0100 Subject: [PATCH 169/256] [6903] Avoid DB access on player invite to channel. --- src/game/Channel.cpp | 9 ++------- src/game/Channel.h | 2 +- src/shared/revision_nr.h | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/game/Channel.cpp b/src/game/Channel.cpp index 22c1a5b1a..d1dee730c 100644 --- a/src/game/Channel.cpp +++ b/src/game/Channel.cpp @@ -626,7 +626,7 @@ void Channel::Invite(uint64 p, const char *newname) SendToOne(&data, newp->GetGUID()); data.clear(); } - MakePlayerInvited(&data, newp->GetGUID()); + MakePlayerInvited(&data, newp->GetName()); SendToOne(&data, p); } @@ -916,13 +916,8 @@ void Channel::MakeNotModerated(WorldPacket *data) } // done 0x1D -void Channel::MakePlayerInvited(WorldPacket *data, uint64 guid) +void Channel::MakePlayerInvited(WorldPacket *data, const std::string& name) { - std::string name; - - if(!objmgr.GetPlayerNameByGUID(guid, name) || name.empty()) - return; // player name not found - MakeNotifyPacket(data, CHAT_PLAYER_INVITED_NOTICE); *data << name; } diff --git a/src/game/Channel.h b/src/game/Channel.h index c3214f824..55ebf57ea 100644 --- a/src/game/Channel.h +++ b/src/game/Channel.h @@ -190,7 +190,7 @@ class Channel void MakeWrongFaction(WorldPacket *data); //? 0x1A void MakeInvalidName(WorldPacket *data); //? 0x1B void MakeNotModerated(WorldPacket *data); //? 0x1C - void MakePlayerInvited(WorldPacket *data, uint64 guid); //+ 0x1D + void MakePlayerInvited(WorldPacket *data, const std::string& name); //+ 0x1D void MakePlayerInviteBanned(WorldPacket *data, uint64 guid); //? 0x1E void MakeThrottled(WorldPacket *data); //? 0x1F void MakeNotInArea(WorldPacket *data); //? 0x20 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index f3c8a6fdf..747b67a5e 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6902" + #define REVISION_NR "6903" #endif // __REVISION_NR_H__ From e848a52da9ee575ccaabdb6cd409307c315af42f Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Sat, 13 Dec 2008 01:12:01 +0300 Subject: [PATCH 170/256] Character re-customization fix --- src/game/Level3.cpp | 28 ++++++++++++++------------- src/game/Player.cpp | 46 +++++++++++++++++++++++++-------------------- src/game/World.cpp | 22 +++++++++++----------- 3 files changed, 52 insertions(+), 44 deletions(-) diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 3c3393876..9931bb39a 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -6504,30 +6504,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 @@ -6539,13 +6536,18 @@ 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, player->GetName(), 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, GetName()); + return true; } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 02f3d062d..e78496246 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -15772,31 +15772,37 @@ void Player::SetFloatValueInDB(uint16 index, float value, uint64 guid) void Player::Customize(uint64 guid, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair) { Tokens tokens; - if(!LoadValuesArrayFromDB(tokens,guid)) + if(!LoadValuesArrayFromDB(tokens, guid)) return; - uint32 player_bytes = atol(tokens[PLAYER_BYTES].c_str()); - ((uint8*)player_bytes)[0] = skin; - ((uint8*)player_bytes)[1] = face; - ((uint8*)player_bytes)[2] = hairStyle; - ((uint8*)player_bytes)[3] = hairColor; - char buf[11]; - snprintf(buf,11,"%u",player_bytes); - tokens[PLAYER_BYTES] = buf; + uint32 unit_bytes0 = GetUInt32ValueFromArray(tokens, UNIT_FIELD_BYTES_0); + uint8 race = unit_bytes0 & 0xFF; + uint8 class_ = (unit_bytes0 >> 8) & 0xFF; - uint32 player_bytes2 = atol(tokens[PLAYER_BYTES_2].c_str()); - ((uint8*)player_bytes2)[0] = facialHair; - char buf2[11]; - snprintf(buf2,11,"%u",player_bytes2); - tokens[PLAYER_BYTES_2] = buf; + PlayerInfo const* info = objmgr.GetPlayerInfo(race, class_); + if(!info) + return; - uint32 player_bytes3 = atol(tokens[PLAYER_BYTES_3].c_str()); - ((uint8*)player_bytes3)[0] = gender; - char buf3[11]; - snprintf(buf3,11,"%u",player_bytes3); - tokens[PLAYER_BYTES_3] = buf; + unit_bytes0 &= ~(0xFF << 16); + unit_bytes0 |= (gender << 16); + SetUInt32ValueInArray(tokens, UNIT_FIELD_BYTES_0, unit_bytes0); - SaveValuesArrayInDB(tokens,guid); + 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() diff --git a/src/game/World.cpp b/src/game/World.cpp index 9794ba523..149833a12 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -226,7 +226,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 @@ -243,10 +243,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 (); @@ -254,7 +254,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); @@ -281,10 +281,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()); // 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()); // 0 - normal, 1 - TBC, must be set in database manually for each account packet << uint32(GetQueuePos (sess)); sess->SendPacket (&packet); @@ -1048,7 +1048,7 @@ 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(); From fcc013071e360a362cf8424119af90e94b84b6bb Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 13 Dec 2008 01:29:23 +0300 Subject: [PATCH 171/256] * Some work under Achievement (add names, enums, comments) Signed-off-by: DiSlord --- src/shared/Database/DBCEnums.h | 7 +++++++ src/shared/Database/DBCStructure.h | 25 ++++++++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/shared/Database/DBCEnums.h b/src/shared/Database/DBCEnums.h index 3f57c7297..8f9d70cb7 100644 --- a/src/shared/Database/DBCEnums.h +++ b/src/shared/Database/DBCEnums.h @@ -76,6 +76,7 @@ enum AchievementCriteriaTypes // 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, @@ -86,6 +87,7 @@ enum AchievementCriteriaTypes 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, @@ -114,13 +116,18 @@ enum AchievementCriteriaTypes 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, diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 8cc274bb1..78f83671e 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -40,7 +40,7 @@ struct AchievementEntry uint32 ID; // 0 uint32 factionFlag; // 1 -1=all, 0=horde, 1=alliance uint32 mapID; // 2 -1=none - //uint32 unk; // 3 parent achievement (previous, required) + //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 @@ -49,11 +49,11 @@ struct AchievementEntry uint32 points; // 39 reward points //uint32 OrderInCategory; // 40 uint32 flags; // 41 - //uint32 icon; // 42 icon - //char *unk1[16]; // 43-58 - //uint32 unk_flags; // 59 - //uint32 count; // 60 - uint32 refAchievement; // 61 related achievement? + //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 @@ -62,7 +62,7 @@ struct AchievementCategoryEntry uint32 parentCategory; // 1 -1 for main category //char *name[16]; // 2-17 //uint32 name_flags; // 18 - uint32 sortOrder; // 19 + //uint32 sortOrder; // 19 }; struct AchievementCriteriaEntry @@ -167,6 +167,12 @@ struct AchievementCriteriaEntry 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 { @@ -340,8 +346,9 @@ struct AchievementCriteriaEntry { 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 @@ -461,7 +468,7 @@ struct AchievementCriteriaEntry uint32 groupFlag; // 27 //uint32 unk1; // 28 uint32 timeLimit; // 29 time limit in seconds - //uint32 order; // 30 order + //uint32 showOrder; // 30 show order }; struct AreaTableEntry From fc5e12c828c81e51d9a04d846aa0adf1df3d800e Mon Sep 17 00:00:00 2001 From: derex Date: Sat, 13 Dec 2008 19:04:02 +0200 Subject: [PATCH 172/256] [6904] Fix possible crash by client sending several times CMSG_PLAYER_LOGIN. --- src/game/CharacterHandler.cpp | 6 ++++++ src/shared/revision_nr.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 8880a7b2e..920bc8b76 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -453,6 +453,12 @@ void WorldSession::HandlePlayerLoginOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); + if(PlayerLoading() || GetPlayer() != NULL) + { + sLog.outError("Player tryes to login again, AccountId = %d",GetAccountId()); + return; + } + m_playerLoading = true; uint64 playerGuid = 0; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 747b67a5e..372a42dfa 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6903" + #define REVISION_NR "6904" #endif // __REVISION_NR_H__ From d97a8d33b975e047b3031b1bf779065b61a74810 Mon Sep 17 00:00:00 2001 From: arrai Date: Sat, 13 Dec 2008 18:59:37 +0100 Subject: [PATCH 173/256] [6905] Fixed items with both healing and energizing effects Store fall information also at MSG_MOVE_FALL_LAND --- src/game/MovementHandler.cpp | 2 +- src/game/Spell.cpp | 32 ++++++++++++++++++++++++++++---- src/shared/revision_nr.h | 2 +- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 922b39e50..372818072 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -362,7 +362,7 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) 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) + 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()) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 458fa8af6..831c1a17d 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4405,6 +4405,8 @@ uint8 Spell::CheckItems() uint32 ItemClass = proto->Class; if (ItemClass == ITEM_CLASS_CONSUMABLE && m_targets.getUnitTarget()) { + // such items should only fail if there is no suitable effect at all - see Rejuvenation Potions for example + uint8 failReason = 0; for (int i = 0; i < 3; i++) { // skip check, pet not required like checks, and for TARGET_PET m_targets.getUnitTarget() is not the real target but the caster @@ -4412,21 +4414,43 @@ uint8 Spell::CheckItems() continue; if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL) + { if (m_targets.getUnitTarget()->GetHealth() == m_targets.getUnitTarget()->GetMaxHealth()) - return (uint8)SPELL_FAILED_ALREADY_AT_FULL_HEALTH; + { + failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_HEALTH; + continue; + } + else + { + failReason = 0; + break; + } + } // Mana Potion, Rage Potion, Thistle Tea(Rogue), ... if (m_spellInfo->Effect[i] == SPELL_EFFECT_ENERGIZE) { if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS) - return (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER; + { + failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER; + continue; + } Powers power = Powers(m_spellInfo->EffectMiscValue[i]); - if (m_targets.getUnitTarget()->GetPower(power) == m_targets.getUnitTarget()->GetMaxPower(power)) - return (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER; + { + failReason = (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER; + continue; + } + else + { + failReason = 0; + break; + } } } + if (failReason) + return failReason; } } } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 372a42dfa..756f31327 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6904" + #define REVISION_NR "6905" #endif // __REVISION_NR_H__ From 6f8f621626bfa3c9bb114145161c69ba51cee36d Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Sat, 13 Dec 2008 22:19:37 +0200 Subject: [PATCH 174/256] [6906] Revert "Reduced number of cells (doubled max visibility distance)." This reverts a part of commit eb60f74c8f9a508fecaa66aa5b8a2fbf026e6479 that caused some performance issues. --- src/game/GridDefines.h | 4 ++-- src/mangosd/mangosd.conf.dist.in | 12 ++++++------ src/shared/revision_nr.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/game/GridDefines.h b/src/game/GridDefines.h index ced42871b..0942c5c31 100644 --- a/src/game/GridDefines.h +++ b/src/game/GridDefines.h @@ -41,10 +41,10 @@ class Player; #define MIN_GRID_DELAY MINUTE*1000 #define MIN_MAP_UPDATE_DELAY 50 -#define MAX_NUMBER_OF_CELLS 4 +#define MAX_NUMBER_OF_CELLS 8 #define SIZE_OF_GRID_CELL (SIZE_OF_GRIDS/MAX_NUMBER_OF_CELLS) -#define CENTER_GRID_CELL_ID 128 +#define CENTER_GRID_CELL_ID 256 #define CENTER_GRID_CELL_OFFSET (SIZE_OF_GRID_CELL/2) #define TOTAL_NUMBER_OF_CELLS_PER_MAP (MAX_NUMBER_OF_GRIDS*MAX_NUMBER_OF_CELLS) diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index a7c0be700..f57e25d5a 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -863,9 +863,9 @@ GM.StartLevel = 1 # Visibility.Distance.Creature # Visibility.Distance.Player # Visibility distance for different in game object -# Max limited by active player zone: ~ 333 +# Max limited by active player zone: ~ 166 # Min limit dependent from objects -# Default: 132 (cell size) +# Default: 66 (cell size) # Min limit is max aggro radius (45) * Rate.Creature.Aggro # # Visibility.Distance.Object @@ -891,10 +891,10 @@ GM.StartLevel = 1 ################################################################################################################### Visibility.GroupMode = 0 -Visibility.Distance.Creature = 132 -Visibility.Distance.Player = 132 -Visibility.Distance.Object = 132 -Visibility.Distance.InFlight = 132 +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 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 756f31327..06202b88f 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6905" + #define REVISION_NR "6906" #endif // __REVISION_NR_H__ From 08a31053126e9de24612ac60b52f8c00b699aa2b Mon Sep 17 00:00:00 2001 From: hunuza Date: Sat, 13 Dec 2008 23:58:52 +0100 Subject: [PATCH 175/256] [6907] Make DB access on char rename async. Signed-off-by: hunuza --- src/game/CharacterHandler.cpp | 70 +++++++++++++++++------------------ src/game/WorldSession.h | 3 +- src/shared/revision_nr.h | 2 +- 3 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 920bc8b76..50c6df71f 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -899,40 +899,14 @@ void WorldSession::HandleToggleCloakOpcode( WorldPacket & /*recv_data*/ ) void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) { - CHECK_PACKET_SIZE(recv_data,8+1); - uint64 guid; std::string newname; - std::string oldname; CHECK_PACKET_SIZE(recv_data, 8+1); recv_data >> guid; recv_data >> newname; - QueryResult *result = CharacterDatabase.PQuery("SELECT at_login, name FROM characters WHERE guid ='%u'", GUID_LOPART(guid)); - if (!result) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_CREATE_ERROR; - SendPacket( &data ); - return; - } - - uint32 at_loginFlags; - Field *fields = result->Fetch(); - at_loginFlags = fields[0].GetUInt32(); - oldname = fields[1].GetCppString(); - delete result; - - if (!(at_loginFlags & AT_LOGIN_RENAME)) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_CREATE_ERROR; - SendPacket( &data ); - return; - } - // prevent character rename to invalid name if(!normalizePlayerName(newname)) { @@ -959,36 +933,58 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) return; } - if(objmgr.GetPlayerGUIDByName(newname)) // character with this name already exist + CharacterDatabase.escape_string(newname); + + CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack, GUID_LOPART(guid), newname, "SELECT guid, at_login, name FROM characters WHERE guid = '%u' XOR name = '%s'", GUID_LOPART(guid), newname.c_str()); +} + +void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uint32 accountId, std::string newname) +{ + WorldSession * session = sWorld.FindSession(accountId); + if(!session) + return; + + if (!result || result->GetRowCount() != 1) { WorldPacket data(SMSG_CHAR_RENAME, 1); data << (uint8)CHAR_CREATE_ERROR; - SendPacket( &data ); + session->SendPacket( &data ); return; } - if(newname == oldname) // checked by client + Field *fields = result->Fetch(); + uint32 guidLow = fields[0].GetUInt32(); + uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER); + uint32 at_loginFlags = fields[1].GetUInt32(); + std::string oldname = fields[2].GetCppString(); + delete result; + if(oldname == newname) { WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_NAME_FAILURE; - SendPacket( &data ); + data << (uint8)CHAR_CREATE_ERROR; + session->SendPacket( &data ); return; } // we have to check character at_login_flag & AT_LOGIN_RENAME also (fake packets hehe) + if (!(at_loginFlags & AT_LOGIN_RENAME)) + { + WorldPacket data(SMSG_CHAR_RENAME, 1); + data << (uint8)CHAR_CREATE_ERROR; + session->SendPacket( &data ); + return; + } - CharacterDatabase.escape_string(newname); - CharacterDatabase.PExecute("UPDATE characters set name = '%s', at_login = at_login & ~ %u WHERE guid ='%u'", newname.c_str(), uint32(AT_LOGIN_RENAME),GUID_LOPART(guid)); - CharacterDatabase.PExecute("DELETE FROM character_declinedname WHERE guid ='%u'", GUID_LOPART(guid)); + 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); - std::string IP_str = GetRemoteAddress(); - sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s",GetAccountId(),IP_str.c_str(),oldname.c_str(),GUID_LOPART(guid),newname.c_str()); + sLog.outChar("Account: %d (IP: %s) Character:[%s] (guid:%u) Changed name to: %s",session->GetAccountId(),session->GetRemoteAddress(),oldname.c_str(),guidLow,newname.c_str()); WorldPacket data(SMSG_CHAR_RENAME,1+8+(newname.size()+1)); data << (uint8)RESPONSE_SUCCESS; data << guid; data << newname; - SendPacket(&data); + session->SendPacket(&data); } void WorldSession::HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data) diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 34a626d80..cd3a4e961 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -91,7 +91,7 @@ class MANGOS_DLL_SPEC WorldSession Player* GetPlayer() const { return _player; } char const* GetPlayerName() const; void SetSecurity(uint32 security) { _security = security; } - std::string& GetRemoteAddress() { return m_Address; } + std::string const& GetRemoteAddress() { return m_Address; } void SetPlayer(Player *plr) { _player = plr; } uint8 Expansion() const { return m_expansion; } @@ -541,6 +541,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleSetActionBar(WorldPacket& recv_data); void HandleChangePlayerNameOpcode(WorldPacket& recv_data); + static void HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uint32 accountId, std::string newname); void HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data); void HandleTotemDestroy(WorldPacket& recv_data); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 06202b88f..a4983290a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6906" + #define REVISION_NR "6907" #endif // __REVISION_NR_H__ From 558909614a2527a34d538923455555a1bf8a24d2 Mon Sep 17 00:00:00 2001 From: TERRANZ Date: Sun, 14 Dec 2008 19:13:26 +0300 Subject: [PATCH 176/256] Implement one hand wielding two-hand weapon ability (warrior talent 46917) Signed-off-by: TERRANZ Small slot checking fixes and make dual wielding dependent from related ability. Signed-off-by: VladimirMangos --- src/game/Player.cpp | 58 +++++++++++++++++++++------------------ src/game/Player.h | 9 ++++++ src/game/Spell.h | 1 + src/game/SpellEffects.cpp | 20 ++++++++------ 4 files changed, 53 insertions(+), 35 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e78496246..4824ef166 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -366,6 +366,7 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) m_canParry = false; m_canBlock = false; m_canDualWield = false; + m_canTitanGrip = false; m_ammoDPS = 0.0f; m_temporaryUnsummonedPetNumber = 0; @@ -7984,7 +7985,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; @@ -7993,6 +7995,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; @@ -8067,14 +8071,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]; } } @@ -9751,33 +9749,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; @@ -18184,9 +18191,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; diff --git a/src/game/Player.h b/src/game/Player.h index 820cef796..3380c7fa7 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1179,6 +1179,11 @@ class MANGOS_DLL_SPEC Player : public Unit // disarm applied only to mainhand weapon return !IsInFeralForm() && (!mainhand || !HasFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_DISARMED) ); } + bool IsTwoHandUsed() const + { + 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); @@ -1817,6 +1822,8 @@ class MANGOS_DLL_SPEC Player : public Unit void SetCanBlock(bool value); bool CanDualWield() const { return m_canDualWield; } void SetCanDualWield(bool value) { m_canDualWield = 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; } @@ -2309,8 +2316,10 @@ class MANGOS_DLL_SPEC Player : public Unit bool m_canParry; bool m_canBlock; bool m_canDualWield; + bool m_canTitanGrip; uint8 m_swingErrorMsg; float m_ammoDPS; + ////////////////////Rest System///////////////////// int time_inn_enter; uint32 inn_pos_mapid; diff --git a/src/game/Spell.h b/src/game/Spell.h index 60c8fc83c..b6b2fbbc8 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -316,6 +316,7 @@ class Spell void EffectKillCredit(uint32 i); void EffectQuestFail(uint32 i); void EffectActivateRune(uint32 i); + void EffectTitanGrip(uint32 i); Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID = 0, Spell** triggeringContainer = NULL ); ~Spell(); diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index b15ffecba..31df57357 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -212,7 +212,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &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::EffectNULL, //155 Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal. + &Spell::EffectTitanGrip, //155 Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal. &Spell::EffectNULL, //156 Add Socket &Spell::EffectNULL, //157 create/learn random item/spell for profession &Spell::EffectMilling, //158 milling @@ -3443,7 +3443,7 @@ void Spell::EffectDispel(uint32 i) void Spell::EffectDualWield(uint32 /*i*/) { - if (unitTarget->GetTypeId() == TYPEID_PLAYER) + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) ((Player*)unitTarget)->SetCanDualWield(true); } @@ -5532,18 +5532,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) @@ -6340,3 +6336,9 @@ void Spell::EffectActivateRune(uint32 i) } } } + +void Spell::EffectTitanGrip(uint32 i) +{ + if (unitTarget && unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->SetCanTitanGrip(true); +} From cb4d97ee1d95598f5160e9e6bdae7227fab8c4a6 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 14 Dec 2008 20:51:27 +0300 Subject: [PATCH 177/256] Some fields comments for ChrClass and ChrRace. Also optimize code (set MAX_RACES to max_player_race+1). Note: MAX_* moved out of enum. This is not nice include value _not_ belong to enum values into enum. Maybe in C this not make sense (enum range = int anyway) but in C++ enum values checked at assigning/etc. --- src/game/SharedDefines.h | 24 +++++++++++++++++------- src/shared/Database/DBCStructure.h | 8 ++++---- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 52614c265..d957f9ecd 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -40,16 +40,24 @@ enum Races RACE_TAUREN = 6, RACE_GNOME = 7, RACE_TROLL = 8, - RACE_GOBLIN = 9, + //RACE_GOBLIN = 9, RACE_BLOODELF = 10, RACE_DRAENEI = 11, - RACE_FEL_ORC = 12, - RACE_NAGA = 13, - RACE_BROKEN = 14, - RACE_SKELETON = 15, - MAX_RACES = 16 + //RACE_FEL_ORC = 12, + //RACE_NAGA = 13, + //RACE_BROKEN = 14, + //RACE_SKELETON = 15, + //RACE_VRYKUL = 16, + //RACE_TUSKARR = 17, + //RACE_FOREST_TROLL = 18, + //RACE_TAUNKA = 19, + //RACE_NORTHREND_SKELETON = 20, + //RACE_ICE_TROLL = 21 }; +// max+1 for player race +#define MAX_RACES 12 + #define RACEMASK_ALL_PLAYABLE \ ((1<<(RACE_HUMAN-1)) |(1<<(RACE_ORC-1)) |(1<<(RACE_DWARF-1)) | \ (1<<(RACE_NIGHTELF-1))|(1<<(RACE_UNDEAD_PLAYER-1))|(1<<(RACE_TAUREN-1)) | \ @@ -70,9 +78,11 @@ enum Classes CLASS_WARLOCK = 9, // CLASS_UNK2 = 10,unused CLASS_DRUID = 11, - MAX_CLASSES = 12 }; +// max+1 for player class +#define MAX_CLASSES 12 + #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))| \ diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 78f83671e..a8f46bea8 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -578,9 +578,9 @@ struct ChrClassesEntry // 3-4, unused //char* name[16]; // 5-20 unused // 21 string flag, unused - //char* string1[16]; // 21-36 unused + //char* nameFemale[16]; // 21-36 unused, if different from base (male) case // 37 string flag, unused - //char* string2[16]; // 38-53 unused + //char* nameNeutralGender[16]; // 38-53 unused, if different from base (male) case // 54 string flag, unused // 55, unused uint32 spellfamily; // 56 @@ -603,9 +603,9 @@ struct ChrRacesEntry uint32 CinematicSequence; // 13 id from CinematicSequences.dbc char* name[16]; // 14-29 used for DBC language detection/selection // 30 string flags, unused - //char* string1[16]; // 31-46 used for DBC language detection/selection + //char* nameFemale[16]; // 31-46, if different from base (male) case // 47 string flags, unused - //char* string2[16]; // 48-63 used for DBC language detection/selection + //char* nameNeutralGender[16]; // 48-63, if different from base (male) case // 64 string flags, unused // 65-67 unused uint32 addon; // 68 (0 - original race, 1 - tbc addon, ...) From 09e8ea2ae6187119f13d2350989c8aa6a7086ef8 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 14 Dec 2008 22:18:00 +0300 Subject: [PATCH 178/256] Update effect 155 name -> SPELL_EFFECT_TITAN_GRIP --- src/game/SharedDefines.h | 2 +- src/game/SpellEffects.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index d957f9ecd..d2185cc10 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -671,7 +671,7 @@ enum SpellEffects SPELL_EFFECT_152 = 152, SPELL_EFFECT_153 = 153, SPELL_EFFECT_154 = 154, - SPELL_EFFECT_155 = 155, + SPELL_EFFECT_TITAN_GRIP = 155, SPELL_EFFECT_ADD_SOCKET = 156, SPELL_EFFECT_157 = 157, SPELL_EFFECT_MILLING = 158, diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 31df57357..044fd8970 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -212,7 +212,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &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 Allows you to equip two-handed axes, maces and swords in one hand, but you attack $49152s1% slower than normal. + &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::EffectNULL, //156 Add Socket &Spell::EffectNULL, //157 create/learn random item/spell for profession &Spell::EffectMilling, //158 milling From c798318b7b359e296b3427ea6b9d337b5f32cfb3 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 14 Dec 2008 22:18:52 +0300 Subject: [PATCH 179/256] Replace hardcoded client(100) and server side (255) level limtation values by defines. --- src/game/Guild.cpp | 2 +- src/game/Level3.cpp | 4 ++-- src/game/MiscHandler.cpp | 6 +++--- src/game/ObjectMgr.cpp | 12 ++++++------ src/game/Player.cpp | 4 ++-- src/game/World.cpp | 26 +++++++++++++------------- src/shared/Database/DBCEnums.h | 8 ++++++++ src/shared/Database/DBCStructure.h | 1 + 8 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index 49efd8a5a..ca6051f22 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -363,7 +363,7 @@ bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot) return false; plLevel = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL, guid); - if(plLevel<1||plLevel>255) // can be at broken `data` field + if(plLevel<1||plLevel>STRONG_MAX_LEVEL) // can be at broken `data` field { sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`data`.",GUID_LOPART(guid)); return false; diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 9931bb39a..3100bbe53 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3814,8 +3814,8 @@ bool ChatHandler::HandleLevelUpCommand(const char* args) int32 newlevel = oldlevel + addlevel; if(newlevel < 1) newlevel = 1; - if(newlevel > 255) // hardcoded maximum level - newlevel = 255; + if(newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level + newlevel = STRONG_MAX_LEVEL; if(chr) { diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index abfcfa2a1..885af56fc 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -81,7 +81,7 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) std::string player_name, guild_name; recv_data >> level_min; // maximal player level, default 0 - recv_data >> level_max; // minimal player level, default 100 + recv_data >> level_max; // minimal player level, default 100 (MAX_LEVEL) recv_data >> player_name; // player name, case sensitive... // recheck @@ -146,8 +146,8 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) // client send in case not set max level value 100 but mangos support 255 max level, // update it to show GMs with characters after 100 level - if(level_max >= 100) - level_max = 255; + if(level_max >= MAX_LEVEL) + level_max = STRONG_MAX_LEVEL; uint32 team = _player->GetTeam(); uint32 security = GetSecurity(); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 98dcc0d15..6c2775218 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -1962,8 +1962,8 @@ void ObjectMgr::LoadPetLevelInfo() uint32 current_level = fields[1].GetUInt32(); if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - if(current_level > 255) // hardcoded level maximum - sLog.outErrorDb("Wrong (> 255) level %u in `pet_levelstats` table, ignoring.",current_level); + if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `pet_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `pet_levelstats` table, ignoring.",current_level); continue; @@ -2339,8 +2339,8 @@ void ObjectMgr::LoadPlayerInfo() uint32 current_level = fields[1].GetUInt32(); if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - if(current_level > 255) // hardcoded level maximum - sLog.outErrorDb("Wrong (> 255) level %u in `player_classlevelstats` table, ignoring.",current_level); + if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `player_classlevelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_classlevelstats` table, ignoring.",current_level); continue; @@ -2434,8 +2434,8 @@ void ObjectMgr::LoadPlayerInfo() uint32 current_level = fields[2].GetUInt32(); if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - if(current_level > 255) // hardcoded level maximum - sLog.outErrorDb("Wrong (> 255) level %u in `player_levelstats` table, ignoring.",current_level); + if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `player_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_levelstats` table, ignoring.",current_level); continue; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 4824ef166..176211868 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -602,7 +602,7 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 if (GetSession()->GetSecurity() >= SEC_MODERATOR) SetUInt32Value(UNIT_FIELD_LEVEL, sWorld.getConfig(CONFIG_START_GM_LEVEL)); else - { + { if(getClass() == CLASS_DEATH_KNIGHT) SetUInt32Value(UNIT_FIELD_LEVEL, 55); else @@ -18719,7 +18719,7 @@ uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 n { uint32 level = getLevel(); - if(level > sGtBarberShopCostBaseStore.GetNumRows()) + if(level > GT_MAX_LEVEL) level = GT_MAX_LEVEL; // max level in this dbc uint8 hairstyle = GetByteValue(PLAYER_BYTES, 2); diff --git a/src/game/World.cpp b/src/game/World.cpp index 149833a12..e20f9c416 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -657,10 +657,10 @@ void World::LoadConfigSettings(bool reload) else m_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfig.GetIntDefault("MaxPlayerLevel", 60); - if(m_configs[CONFIG_MAX_PLAYER_LEVEL] > 100) + if(m_configs[CONFIG_MAX_PLAYER_LEVEL] > MAX_LEVEL) { - sLog.outError("MaxPlayerLevel (%i) must be in range 1..100. Set to 100.",m_configs[CONFIG_MAX_PLAYER_LEVEL]); - m_configs[CONFIG_MAX_PLAYER_LEVEL] = 100; + sLog.outError("MaxPlayerLevel (%i) must be in range 1..%u. Set to %u.",m_configs[CONFIG_MAX_PLAYER_LEVEL],MAX_LEVEL,MAX_LEVEL); + m_configs[CONFIG_MAX_PLAYER_LEVEL] = MAX_LEVEL; } m_configs[CONFIG_START_PLAYER_LEVEL] = sConfig.GetIntDefault("StartPlayerLevel", 1); @@ -763,14 +763,14 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_START_GM_LEVEL] = sConfig.GetIntDefault("GM.StartLevel", 1); if(m_configs[CONFIG_START_GM_LEVEL] < m_configs[CONFIG_START_PLAYER_LEVEL]) { - sLog.outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..100. Set to %u.", - m_configs[CONFIG_START_GM_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL], m_configs[CONFIG_START_PLAYER_LEVEL]); + sLog.outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..%u. Set to %u.", + m_configs[CONFIG_START_GM_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL], MAX_LEVEL, m_configs[CONFIG_START_PLAYER_LEVEL]); m_configs[CONFIG_START_GM_LEVEL] = m_configs[CONFIG_START_PLAYER_LEVEL]; } - else if(m_configs[CONFIG_START_GM_LEVEL] > 100) + else if(m_configs[CONFIG_START_GM_LEVEL] > MAX_LEVEL) { - sLog.outError("GM.StartLevel (%i) must be in range 1..100. Set to %u.", m_configs[CONFIG_START_GM_LEVEL], 100); - m_configs[CONFIG_START_GM_LEVEL] = 100; + 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_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode",0); @@ -862,13 +862,13 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_WORLD_BOSS_LEVEL_DIFF] = sConfig.GetIntDefault("WorldBossLevelDiff",3); - // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level (100) + // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level MAX_LEVEL(100) m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.LowLevelHideDiff", 4); - if(m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > 100) - m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = 100; + if(m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > MAX_LEVEL) + m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = MAX_LEVEL; m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.HighLevelHideDiff", 7); - if(m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > 100) - m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = 100; + if(m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > MAX_LEVEL) + m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = MAX_LEVEL; m_configs[CONFIG_DETECT_POS_COLLISION] = sConfig.GetBoolDefault("DetectPosCollision", true); diff --git a/src/shared/Database/DBCEnums.h b/src/shared/Database/DBCEnums.h index 8f9d70cb7..4f406c9cc 100644 --- a/src/shared/Database/DBCEnums.h +++ b/src/shared/Database/DBCEnums.h @@ -19,6 +19,14 @@ #ifndef DBCENUMS_H #define DBCENUMS_H +// client supported max level for player/pets/etc. Avoid overflow or client stability affected. +// also see GT_MAX_LEVEL define +#define MAX_LEVEL 100 + +// Server side limitation. Base at used code requirements. +// also see MAX_LEVEL and GT_MAX_LEVEL define +#define STRONG_MAX_LEVEL 255 + enum AreaTeams { AREATEAM_NONE = 0, diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index a8f46bea8..cf08161c3 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -741,6 +741,7 @@ struct GlyphSlotEntry uint32 Order; }; +// All Gt* DBC store data for 100 levels, some by 100 per class/race #define GT_MAX_LEVEL 100 struct GtBarberShopCostBaseEntry From f5c4fe86e8b51c52348d0e384ba1264a28dad84e Mon Sep 17 00:00:00 2001 From: bloutix Date: Sun, 14 Dec 2008 23:14:17 +0300 Subject: [PATCH 180/256] Correctly select GM level in case heroic class. Signed-off-by: bloutix Move heroic class starting level to mangos.conf Signed-off-by: VladimirMangos --- src/game/Player.cpp | 15 +++++++++------ src/game/World.cpp | 14 ++++++++++++++ src/game/World.h | 1 + src/mangosd/mangosd.conf.dist.in | 7 ++++++- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 176211868..ead650591 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -599,16 +599,19 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 } // 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 { - if(getClass() == CLASS_DEATH_KNIGHT) - SetUInt32Value(UNIT_FIELD_LEVEL, 55); - 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)); diff --git a/src/game/World.cpp b/src/game/World.cpp index e20f9c416..8da99d209 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -675,6 +675,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) { diff --git a/src/game/World.h b/src/game/World.h index a89ef9abd..7af514469 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -103,6 +103,7 @@ enum WorldConfigs 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, diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index e2ce71475..c42da5204 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -417,12 +417,16 @@ LogColors = "" # MaxPlayerLevel # Max level that can be reached by player for experience (in range from 1 to 100). # Change not recommended -# Default: 70 +# 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) @@ -573,6 +577,7 @@ CharactersPerRealm = 10 SkipCinematics = 0 MaxPlayerLevel = 80 StartPlayerLevel = 1 +StartHeroicPlayerLevel = 55 StartPlayerMoney = 0 MaxHonorPoints = 75000 StartHonorPoints = 0 From 5113af643ecda19b3058e091034befd851ce7847 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 14 Dec 2008 20:51:27 +0300 Subject: [PATCH 181/256] Some fields comments for ChrClass and ChrRace. Also optimize code (set MAX_RACES to max_player_race+1). Note: MAX_* moved out of enum. This is not nice include value _not_ belong to enum values into enum. Maybe in C this not make sense (enum range = int anyway) but in C++ enum values checked at assigning/etc. (cherry picked from commit f157c4e3d5e18878c7ab0dae383acb7704c3ed90) --- src/game/SharedDefines.h | 24 +++++++++++++++++------- src/shared/Database/DBCStructure.h | 8 ++++---- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 8ae1cf27b..534e3a9ff 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -40,16 +40,24 @@ enum Races RACE_TAUREN = 6, RACE_GNOME = 7, RACE_TROLL = 8, - RACE_GOBLIN = 9, + //RACE_GOBLIN = 9, RACE_BLOODELF = 10, RACE_DRAENEI = 11, - RACE_FEL_ORC = 12, - RACE_NAGA = 13, - RACE_BROKEN = 14, - RACE_SKELETON = 15, - MAX_RACES = 16 + //RACE_FEL_ORC = 12, + //RACE_NAGA = 13, + //RACE_BROKEN = 14, + //RACE_SKELETON = 15, + //RACE_VRYKUL = 16, + //RACE_TUSKARR = 17, + //RACE_FOREST_TROLL = 18, + //RACE_TAUNKA = 19, + //RACE_NORTHREND_SKELETON = 20, + //RACE_ICE_TROLL = 21 }; +// max+1 for player race +#define MAX_RACES 12 + #define RACEMASK_ALL_PLAYABLE \ ((1<<(RACE_HUMAN-1)) |(1<<(RACE_ORC-1)) |(1<<(RACE_DWARF-1)) | \ (1<<(RACE_NIGHTELF-1))|(1<<(RACE_UNDEAD_PLAYER-1))|(1<<(RACE_TAUREN-1)) | \ @@ -70,9 +78,11 @@ enum Classes CLASS_WARLOCK = 9, // CLASS_UNK2 = 10,unused CLASS_DRUID = 11, - MAX_CLASSES = 12 }; +// max+1 for player class +#define MAX_CLASSES 12 + #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))| \ diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 59d5d18c4..1d32bfd35 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -128,9 +128,9 @@ struct ChrClassesEntry // 4, unused //char* name[16]; // 5-20 unused // 21 string flag, unused - //char* string1[16]; // 21-36 unused + //char* nameFemale[16]; // 21-36 unused, if different from base (male) case // 37 string flag, unused - //char* string2[16]; // 38-53 unused + //char* nameNeutralGender[16]; // 38-53 unused, if different from base (male) case // 54 string flag, unused // 55, unused uint32 spellfamily; // 56 @@ -151,9 +151,9 @@ struct ChrRacesEntry uint32 startmovie; // 13 id from CinematicCamera.dbc char* name[16]; // 14-29 used for DBC language detection/selection // 30 string flags, unused - //char* string1[16]; // 31-46 used for DBC language detection/selection + //char* nameFemale[16]; // 31-46, if different from base (male) case // 47 string flags, unused - //char* string2[16]; // 48-63 used for DBC language detection/selection + //char* nameNeutralGender[16]; // 48-63, if different from base (male) case // 64 string flags, unused // 65-67 unused uint32 addon; // 68 (0 - original race, 1 - tbc addon, ...) From 35f54d365df41bd4cc0333235c0dc039578cd9d8 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 14 Dec 2008 23:52:32 +0300 Subject: [PATCH 182/256] Replace hardcoded client(100) and server side (255) level limtation values by defines. (cherry picked from commit 389a1784e288f11587067d3a6d4b70cce9214cb9) Conflicts: src/game/Player.cpp src/game/World.cpp src/shared/Database/DBCStructure.h --- src/game/Guild.cpp | 2 +- src/game/Level3.cpp | 4 ++-- src/game/MiscHandler.cpp | 6 +++--- src/game/ObjectMgr.cpp | 12 ++++++------ src/game/World.cpp | 31 +++++++++++++++--------------- src/shared/Database/DBCEnums.h | 8 ++++++++ src/shared/Database/DBCStructure.h | 1 + 7 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index 8076757b5..bf6a3ab18 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -363,7 +363,7 @@ bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot) return false; plLevel = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL, guid); - if(plLevel<1||plLevel>255) // can be at broken `data` field + if(plLevel<1||plLevel>STRONG_MAX_LEVEL) // can be at broken `data` field { sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`data`.",GUID_LOPART(guid)); return false; diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 4b6372f53..8ede8ba91 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -3805,8 +3805,8 @@ bool ChatHandler::HandleLevelUpCommand(const char* args) int32 newlevel = oldlevel + addlevel; if(newlevel < 1) newlevel = 1; - if(newlevel > 255) // hardcoded maximum level - newlevel = 255; + if(newlevel > STRONG_MAX_LEVEL) // hardcoded maximum level + newlevel = STRONG_MAX_LEVEL; if(chr) { diff --git a/src/game/MiscHandler.cpp b/src/game/MiscHandler.cpp index b2c7d7d5a..881270189 100644 --- a/src/game/MiscHandler.cpp +++ b/src/game/MiscHandler.cpp @@ -80,7 +80,7 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) std::string player_name, guild_name; recv_data >> level_min; // maximal player level, default 0 - recv_data >> level_max; // minimal player level, default 100 + recv_data >> level_max; // minimal player level, default 100 (MAX_LEVEL) recv_data >> player_name; // player name, case sensitive... // recheck @@ -145,8 +145,8 @@ void WorldSession::HandleWhoOpcode( WorldPacket & recv_data ) // client send in case not set max level value 100 but mangos support 255 max level, // update it to show GMs with characters after 100 level - if(level_max >= 100) - level_max = 255; + if(level_max >= MAX_LEVEL) + level_max = STRONG_MAX_LEVEL; uint32 team = _player->GetTeam(); uint32 security = GetSecurity(); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 1fbdf62c8..040c3ce35 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -1909,8 +1909,8 @@ void ObjectMgr::LoadPetLevelInfo() uint32 current_level = fields[1].GetUInt32(); if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - if(current_level > 255) // hardcoded level maximum - sLog.outErrorDb("Wrong (> 255) level %u in `pet_levelstats` table, ignoring.",current_level); + if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `pet_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `pet_levelstats` table, ignoring.",current_level); continue; @@ -2286,8 +2286,8 @@ void ObjectMgr::LoadPlayerInfo() uint32 current_level = fields[1].GetUInt32(); if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - if(current_level > 255) // hardcoded level maximum - sLog.outErrorDb("Wrong (> 255) level %u in `player_classlevelstats` table, ignoring.",current_level); + if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `player_classlevelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_classlevelstats` table, ignoring.",current_level); continue; @@ -2381,8 +2381,8 @@ void ObjectMgr::LoadPlayerInfo() uint32 current_level = fields[2].GetUInt32(); if(current_level > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - if(current_level > 255) // hardcoded level maximum - sLog.outErrorDb("Wrong (> 255) level %u in `player_levelstats` table, ignoring.",current_level); + if(current_level > STRONG_MAX_LEVEL) // hardcoded level maximum + sLog.outErrorDb("Wrong (> %u) level %u in `player_levelstats` table, ignoring.",STRONG_MAX_LEVEL,current_level); else sLog.outDetail("Unused (> MaxPlayerLevel in mangosd.conf) level %u in `player_levelstats` table, ignoring.",current_level); continue; diff --git a/src/game/World.cpp b/src/game/World.cpp index f66846362..e6623a29a 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -650,10 +650,11 @@ void World::LoadConfigSettings(bool reload) } else m_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfig.GetIntDefault("MaxPlayerLevel", 60); - if(m_configs[CONFIG_MAX_PLAYER_LEVEL] > 255) + + if(m_configs[CONFIG_MAX_PLAYER_LEVEL] > MAX_LEVEL) { - sLog.outError("MaxPlayerLevel (%i) must be in range 1..255. Set to 255.",m_configs[CONFIG_MAX_PLAYER_LEVEL]); - m_configs[CONFIG_MAX_PLAYER_LEVEL] = 255; + sLog.outError("MaxPlayerLevel (%i) must be in range 1..%u. Set to %u.",m_configs[CONFIG_MAX_PLAYER_LEVEL],MAX_LEVEL,MAX_LEVEL); + m_configs[CONFIG_MAX_PLAYER_LEVEL] = MAX_LEVEL; } m_configs[CONFIG_START_PLAYER_LEVEL] = sConfig.GetIntDefault("StartPlayerLevel", 1); @@ -756,14 +757,14 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_START_GM_LEVEL] = sConfig.GetIntDefault("GM.StartLevel", 1); if(m_configs[CONFIG_START_GM_LEVEL] < m_configs[CONFIG_START_PLAYER_LEVEL]) { - sLog.outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..255. Set to %u.", - m_configs[CONFIG_START_GM_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL]); + sLog.outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..%u. Set to %u.", + m_configs[CONFIG_START_GM_LEVEL],m_configs[CONFIG_START_PLAYER_LEVEL], MAX_LEVEL, m_configs[CONFIG_START_PLAYER_LEVEL]); m_configs[CONFIG_START_GM_LEVEL] = m_configs[CONFIG_START_PLAYER_LEVEL]; } - else if(m_configs[CONFIG_START_GM_LEVEL] > 255) + else if(m_configs[CONFIG_START_GM_LEVEL] > MAX_LEVEL) { - sLog.outError("GM.StartLevel (%i) must be in range 1..255. Set to %u.",m_configs[CONFIG_START_GM_LEVEL],255); - m_configs[CONFIG_START_GM_LEVEL] = 255; + 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_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode",0); @@ -854,13 +855,13 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_WORLD_BOSS_LEVEL_DIFF] = sConfig.GetIntDefault("WorldBossLevelDiff",3); - // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level (255) - m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.LowLevelHideDiff",4); - if(m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > 255) - m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = 255; - m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.HighLevelHideDiff",7); - if(m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > 255) - m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = 255; + // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level MAX_LEVEL(100) + m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.LowLevelHideDiff", 4); + if(m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > MAX_LEVEL) + m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = MAX_LEVEL; + m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.HighLevelHideDiff", 7); + if(m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > MAX_LEVEL) + m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = MAX_LEVEL; m_configs[CONFIG_DETECT_POS_COLLISION] = sConfig.GetBoolDefault("DetectPosCollision", true); diff --git a/src/shared/Database/DBCEnums.h b/src/shared/Database/DBCEnums.h index 6ad7fdb12..1d54616a2 100644 --- a/src/shared/Database/DBCEnums.h +++ b/src/shared/Database/DBCEnums.h @@ -19,6 +19,14 @@ #ifndef DBCENUMS_H #define DBCENUMS_H +// client supported max level for player/pets/etc. Avoid overflow or client stability affected. +// also see GT_MAX_LEVEL define +#define MAX_LEVEL 100 + +// Server side limitation. Base at used code requirements. +// also see MAX_LEVEL and GT_MAX_LEVEL define +#define STRONG_MAX_LEVEL 255 + enum AreaTeams { AREATEAM_NONE = 0, diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 1d32bfd35..acabe18f5 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -267,6 +267,7 @@ struct GemPropertiesEntry uint32 color; }; +// All Gt* DBC store data for 100 levels, some by 100 per class/race #define GT_MAX_LEVEL 100 struct GtCombatRatingsEntry From a62801aee9566d56090a6f518223e37a0ed8a184 Mon Sep 17 00:00:00 2001 From: balrok Date: Mon, 15 Dec 2008 00:11:12 +0300 Subject: [PATCH 183/256] [6908] Faster setting online=0 at startup and semilar queries. Signed-off-by: VladimirMangos --- src/game/Level2.cpp | 2 +- src/game/Level3.cpp | 2 +- src/mangosd/Master.cpp | 2 +- src/shared/revision_nr.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index 901d7513b..db1a6bbfa 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -3137,7 +3137,7 @@ bool ChatHandler::HandleWpShowCommand(const char* args) } }while(result->NextRow()); // set "wpguid" column to "empty" - no visual waypoint spawned - WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0'"); + WorldDatabase.PExecuteLog("UPDATE creature_movement SET wpguid = '0' WHERE wpguid <> '0'"); if( hasError ) { diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 8ede8ba91..fb2c79bce 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -4564,7 +4564,7 @@ bool ChatHandler::HandleResetAllCommand(const char * args) return false; } - CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u'",atLogin); + CharacterDatabase.PExecute("UPDATE characters SET at_login = at_login | '%u' WHERE (at_login & '%u') = '0'",atLogin,atLogin); HashMapHolder::MapType const& plist = ObjectAccessor::Instance().GetPlayers(); for(HashMapHolder::MapType::const_iterator itr = plist.begin(); itr != plist.end(); ++itr) itr->second->SetAtLoginFlag(atLogin); diff --git a/src/mangosd/Master.cpp b/src/mangosd/Master.cpp index 1b6929267..f5ef907bb 100644 --- a/src/mangosd/Master.cpp +++ b/src/mangosd/Master.cpp @@ -459,7 +459,7 @@ void Master::clearOnlineAccounts() "AND id IN (SELECT acctid FROM realmcharacters WHERE realmid = '%d')",realmID); - CharacterDatabase.Execute("UPDATE characters SET online = 0"); + CharacterDatabase.Execute("UPDATE characters SET online = 0 WHERE online<>0"); } /// Handle termination signals diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index a4983290a..2d7234568 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6907" + #define REVISION_NR "6908" #endif // __REVISION_NR_H__ From c875fd698fca8d48ebde1e0000c34d784fa0cf8a Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 15 Dec 2008 00:33:32 +0300 Subject: [PATCH 184/256] Fixed typo in map extractor. Patch provided by andstan. --- contrib/extractor/System.cpp | 13 +++++---- contrib/extractor/ad.exe | Bin 160768 -> 160768 bytes contrib/extractor/adt.cpp | 52 +++++++++++++++++------------------ contrib/extractor/adt.h | 47 +++++++++++++++++-------------- 4 files changed, 60 insertions(+), 52 deletions(-) diff --git a/contrib/extractor/System.cpp b/contrib/extractor/System.cpp index 3b659a4c6..85d06369f 100644 --- a/contrib/extractor/System.cpp +++ b/contrib/extractor/System.cpp @@ -18,9 +18,10 @@ extern ArchiveSet gOpenArchives; bool ConvertADT(char*, char*); -typedef struct{ +typedef struct +{ char name[64]; - unsigned int id; + uint32 id; } map_id; typedef unsigned char uint8; @@ -143,7 +144,7 @@ void ReadAreaTableDBC() size_t area_count = dbc.getRecordCount(); size_t maxid = dbc.getMaxId(); areas = new uint16[maxid + 1]; - memset(areas, 0xff, sizeof(areas)); + memset(areas, 0xff, (maxid + 1) * sizeof(uint16)); for(uint32 x = 0; x < area_count; ++x) areas[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); @@ -199,7 +200,7 @@ void ExtractMapsFromMpq() ConvertADT(mpq_filename, output_filename); done++; } - // draw progess bar + // draw progress bar printf("Processing........................%d%%\r", (100 * done) / total); } } @@ -243,7 +244,7 @@ void ExtractDBCFiles(int locale, bool basicLocale) string filename = path; filename += (iter->c_str() + strlen("DBFilesClient\\")); - FILE *output=fopen(filename.c_str(), "wb"); + FILE *output = fopen(filename.c_str(), "wb"); if(!output) { printf("Can't create the output file '%s'\n", filename.c_str()); @@ -295,7 +296,7 @@ void LoadCommonMPQFiles() if(i > 1) sprintf(ext, "-%i", i); - sprintf(filename,"%s/Data/patch%s.MPQ", input_path, ext); + sprintf(filename, "%s/Data/patch%s.MPQ", input_path, ext); if(FileExists(filename)) new MPQArchive(filename); } diff --git a/contrib/extractor/ad.exe b/contrib/extractor/ad.exe index 30d3f314dafc36ed83575e1d99f9bf07e886e056..f483f3892f9135033e8b6e9e4786d983c5c5b8b1 100755 GIT binary patch delta 14215 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 xag3NqI9v_qabl_GpN*JJ5Y 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 diff --git a/contrib/extractor/adt.cpp b/contrib/extractor/adt.cpp index f0c3de960..dde87e5fc 100644 --- a/contrib/extractor/adt.cpp +++ b/contrib/extractor/adt.cpp @@ -15,7 +15,7 @@ #include "adt.h" #include "mpq_libmpq.h" -unsigned int iRes = 256; +uint32 iRes = 256; extern uint16 *areas; extern uint16 *LiqType; extern uint32 maxAreaId; @@ -23,7 +23,6 @@ extern uint32 maxAreaId; vec wmoc; Cell *cell; -//uint32 wmo_count; mcell *mcells; int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; @@ -40,26 +39,23 @@ bool LoadADT(char* filename) } MapLiqFlag = new uint8[256]; - for(int j = 0; j < 256; ++j) + for(uint32 j = 0; j < 256; ++j) MapLiqFlag[j] = 0; // no water MapLiqHeight = new float[16384]; - for(int j = 0; j < 16384; ++j) + for(uint32 j = 0; j < 16384; ++j) MapLiqHeight[j] = -999999; // no water - mcells=new mcell; + mcells = new mcell; - wmoc.x =65 * TILESIZE; - wmoc.z =65 * TILESIZE; + wmoc.x = 65 * TILESIZE; + wmoc.z = 65 * TILESIZE; size_t mcnk_offsets[256], mcnk_sizes[256]; - //wmo_count = 0; - //bool found = false; - - MH2O_presence = false; chunk_num = 0; k = 0; + m = 0; while (!mf.isEof()) { uint32 fourcc; @@ -72,7 +68,7 @@ bool LoadADT(char* filename) //if(fourcc==0x4d564552) // MVER if(fourcc == 0x4d43494e) // MCIN { - for (int i = 0; i < 256; ++i) + for (uint32 i = 0; i < 256; ++i) { mf.read(&mcnk_offsets[i], 4); mf.read(&mcnk_sizes[i], 4); @@ -86,24 +82,23 @@ bool LoadADT(char* filename) //if(fourcc == 0x4d574944) // MWID offsets for strings in MWMO //if(fourcc == 0x4d444446) // MDDF //if(fourcc == 0x4d4f4446) // MODF - if(fourcc == 0x4d48324f && size) // MH2O new in WotLK + if(fourcc == 0x4d48324f) // MH2O new in WotLK { - MH2O_presence = true; // çäåñü íàäî çàïîìíèòü áàçîâóþ ïîçèöèþ â ôàéëå òê âñå ñìåùåíèÿ áóäóò îò íåãî uint32 base_pos = mf.getPos(); uint32 header_pos = 0; - LiqOffsData = new MH2O_offsData; - LiqChunkData1 = new MH2O_Data1; - ChunkLiqHeight = new float[81]; - for(;chunk_num < 256; ++chunk_num) + MH2O_offsData *LiqOffsData = new MH2O_offsData; + MH2O_Data1 *LiqChunkData1 = new MH2O_Data1; + float *ChunkLiqHeight = new float[81]; + for(chunk_num = 0; chunk_num < 256; ++chunk_num) { - mf.read(LiqOffsData, 12); + mf.read(LiqOffsData, 0x0C); header_pos = mf.getPos(); if(LiqOffsData->offsData1 != 0) // åñëè äàííûå â Data1 î âîäå åñòü, òî èõ íàäî êîíâåðòèðîâàòü { // ïåðåõîäèì ïî ñìåùåíèþ èç offsData1 ÎÒ ÍÀ×ÀËÀ êóñêà mf.seek(base_pos + LiqOffsData->offsData1); - mf.read(LiqChunkData1, 24); // ñ÷èòûâàåì ñàìè äàííûå â ñòðóêòóðó òèïà MH2O_Data1 + mf.read(LiqChunkData1, 0x18); // ñ÷èòûâàåì ñàìè äàííûå â ñòðóêòóðó òèïà MH2O_Data1 // çàíîñèì äàííûå ôëàãà äëÿ êóñêà if(LiqType[LiqChunkData1->LiquidTypeId] == 0xffff) printf("\nCan't find Liquid type for map %s\nchunk %d\n", filename, chunk_num); @@ -132,6 +127,7 @@ bool LoadADT(char* filename) for(int j = 0; j < 81; ++j) ChunkLiqHeight[j] = -999999; // no liquid/water } + if(!(chunk_num % 16)) m = 1024 * (chunk_num / 16); // ñìåùåíèå ïî ðÿäàì êóñêîâ ñ ïåðåêðûòèåì = 1024 k = m + (chunk_num % 16) * 8; // óñòàíàâëèâàåìñÿ íà íà÷àëüíûé èíäåêñ äëÿ çàïîëíåíèÿ ðÿäà @@ -160,6 +156,9 @@ bool LoadADT(char* filename) //printf("Loading chunks info\n"); // read individual map chunks + chunk_num = 0; + k = 0; + m = 0; for (int j = 0; j < 16; ++j) { for (int i = 0; i < 16; ++i) @@ -245,14 +244,14 @@ inline void LoadMapChunk(MPQFile &mf, chunk *_chunk) { nextpos = mf.getPos() + 0x1C0; // size fix } - else if(fourcc == 0x4d434c51 && !MH2O_presence) // íå áóäåì ó÷èòûâàòü åñëè óæå áûëè äàííûå â MH2O, ïåðåñòðàõîâêà :) // MCLQ + else if(fourcc == 0x4d434c51) // íå áóäåì ó÷èòûâàòü åñëè óæå áûëè äàííûå â MH2O, ïåðåñòðàõîâêà :) // MCLQ { // liquid / water level char fcc1[5]; mf.read(fcc1, 4); flipcc(fcc1); fcc1[4] = 0; - ChunkLiqHeight = new float[81]; + float *ChunkLiqHeight = new float[81]; if (!strcmp(fcc1, "MCSE")) { @@ -267,9 +266,10 @@ inline void LoadMapChunk(MPQFile &mf, chunk *_chunk) mf.read(&maxheight, 4); for(int j = 0; j < 81; ++j) { - mf.read(&h, 4); - mf.read(&h, 4); - if(h > maxheight) + LiqData liq; + mf.read(&liq, 8); + + if(liq.height > maxheight) ChunkLiqHeight[j] = -999999; else ChunkLiqHeight[j] = h; @@ -283,7 +283,7 @@ inline void LoadMapChunk(MPQFile &mf, chunk *_chunk) // çàïîëíåì òàê æå êàê â MH2O if(!(chunk_num % 16)) m = 1024 * (chunk_num / 16); - k = m +(chunk_num % 16) * 8; + k = m + (chunk_num % 16) * 8; for(int p = 0; p < 72; p += 9) { diff --git a/contrib/extractor/adt.h b/contrib/extractor/adt.h index 7fb8dc078..d56501c90 100644 --- a/contrib/extractor/adt.h +++ b/contrib/extractor/adt.h @@ -9,43 +9,45 @@ typedef unsigned char uint8; typedef unsigned short uint16; typedef unsigned int uint32; class Liquid; -typedef struct { +typedef struct +{ float x; float y; float z; } svec; -typedef struct { +typedef struct +{ double x; double y; double z; } vec; -typedef struct{ +typedef struct +{ vec v[3]; } triangle; -typedef struct{ - float v9[16*8+1][16*8+1]; - float v8[16*8][16*8]; +typedef struct +{ + float v9[16 * 8 + 1][16 * 8 + 1]; + float v8[16 * 8][16 * 8]; } Cell; -typedef struct{ +typedef struct +{ double v9[9][9]; double v8[8][8]; uint16 area_id; } chunk; -class WMO; -class WMOManager; -void fixname(std::string &name); - typedef struct { chunk ch[16][16]; } mcell; -struct MapChunkHeader { +struct MapChunkHeader +{ uint32 flags; uint32 ix; uint32 iy; @@ -81,13 +83,15 @@ struct MapChunkHeader { uint32 effectId; }; -typedef struct { +typedef struct +{ uint32 offsData1; uint32 used; uint32 offsData2; } MH2O_offsData; -typedef struct { +typedef struct +{ uint16 LiquidTypeId; uint16 type; float heightLevel1; @@ -100,6 +104,13 @@ typedef struct { uint32 ofsData2b; } MH2O_Data1; +typedef struct +{ + uint16 unk1; + uint16 unk2; + float height; +} LiqData; + enum LiquidType { LIQUID_TYPE_WATER = 0, @@ -110,12 +121,8 @@ enum LiquidType class MPQFile; -bool MH2O_presence; -MH2O_offsData *LiqOffsData; -MH2O_Data1 *LiqChunkData1; -float *ChunkLiqHeight, *MapLiqHeight; -uint8* MapLiqFlag; +float *MapLiqHeight; +uint8 *MapLiqFlag; uint32 k, m, chunk_num; void LoadMapChunk(MPQFile &, chunk*); -bool LoadWMO(char* filename); #endif From 344e3b02e3719487b4ac5418583be93ea2df6cc1 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 15 Dec 2008 00:37:17 +0300 Subject: [PATCH 185/256] whitespace removed --- contrib/extractor/adt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/extractor/adt.h b/contrib/extractor/adt.h index d56501c90..52196c4e7 100644 --- a/contrib/extractor/adt.h +++ b/contrib/extractor/adt.h @@ -104,7 +104,7 @@ typedef struct uint32 ofsData2b; } MH2O_Data1; -typedef struct +typedef struct { uint16 unk1; uint16 unk2; From f7701b87a104b029ed204dd942cc223c7b08d762 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Mon, 15 Dec 2008 02:07:24 +0300 Subject: [PATCH 186/256] Some work vs SPELL_AURA_PERIODIC_DUMMY aura * Optimisation * Implement Warrior 61216 and ranks * Implement Druid 22842 * Implement Hunter 53301 and ranks, 53511 and ranks * Implement DK 45524 and related spells, 48978 and ranks * Some comments for future Signed-off-by: DiSlord --- src/game/SpellAuras.cpp | 381 ++++++++++++++++++++++++++++++---------- 1 file changed, 292 insertions(+), 89 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 9340ded48..a95af3fcb 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2320,6 +2320,8 @@ void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) if(!Real) return; + Unit* caster = GetCaster(); + SpellEntry const*spell = GetSpellProto(); switch( spell->SpellFamilyName) { @@ -2343,6 +2345,16 @@ void Aura::HandleAuraPeriodicDummy(bool apply, bool Real) ((Player*)m_target)->UpdateManaRegen(); break; } + // Explosive Shot + if (spell->SpellFamilyFlags & 0x8000000000000000LL) + { + if (apply && caster) + { + int32 damage = m_modifier.m_amount + caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100; + caster->CastCustomSpell(m_target, 53352, &damage, 0, 0, true, 0, this); + } + break; + } break; } } @@ -6092,114 +6104,136 @@ void Aura::PeriodicTick() void Aura::PeriodicDummyTick() { + Unit *caster = GetCaster(); SpellEntry const* spell = GetSpellProto(); - switch (spell->Id) + switch (spell->SpellFamilyName) { - // 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 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()) - { - // Get tick number - int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime; - // Default case (not on arenas) - if (tick == 0) - { - (*i)->GetModifier()->m_amount = m_modifier.m_amount; - ((Player*)m_target)->UpdateManaRegen(); - // Disable continue - m_isPeriodic = false; - } + if (m_target->GetTypeId() != TYPEID_PLAYER) 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) + // 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) + { + if ((*i)->GetId() == GetId()) { - 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 + // Get tick number + int32 tick = (m_maxduration - m_duration) / m_modifier.periodictime; + // Default case (not on arenas) + if (tick == 0) + { (*i)->GetModifier()->m_amount = m_modifier.m_amount; - break; + ((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;*/ } - ((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) + + // TODO: now its not periodic dummy - need move out from here + // Aspect of the Viper + case 34074: + { + if (m_target->GetTypeId() != TYPEID_PLAYER) + return; + // Should be manauser + if (m_target->getPowerType()!=POWER_MANA) + return; + 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; - // 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 @@ -6212,6 +6246,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) @@ -6260,6 +6296,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 @@ -6326,14 +6364,179 @@ 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 & 0x8000000000000000LL) + { + if (!caster) + return; + // Skip 0 tick + if (m_duration < m_modifier.periodictime) + return; + int32 damage = caster->CalculateSpellDamage(spell, GetEffIndex(), GetBasePoints(), m_target); + damage+=caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 8 / 100; + 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) +// return; + break; + } + case SPELLFAMILY_DEATHKNIGHT: + { + // Death and Decay +// if (spell->SpellFamilyFlags & 0x0000000000000020LL) +// return; + // Raise Dead +// if (spell->SpellFamilyFlags & 0x0000000000001000LL) +// return; + // Chains of Ice + if (spell->SpellFamilyFlags & 0x0000400000000000LL) + { + // 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; } From a89080730dbdf0d6372f6b85dddbf7f7cfbf8acc Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 15 Dec 2008 03:08:01 +0300 Subject: [PATCH 187/256] [6909] Correctly equip all possible amount non stackable items from custom initial items with >1 amount instead equip single and ignore other. Also corrently report error at buy to equip slot not single item (impossible using normal client way) instead silencely ingnore amount and equip single by stack price. --- src/game/Player.cpp | 46 +++++++++++++++++++++++++--------------- src/game/Player.h | 6 +++--- src/shared/revision_nr.h | 2 +- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 3b5494057..60f89f5ce 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -668,12 +668,12 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 } } - StoreNewItemInBestSlot(item_id, count); + StoreNewItemInBestSlots(item_id, count); } } for (PlayerCreateInfoItems::const_iterator item_id_itr = info->item.begin(); item_id_itr!=info->item.end(); ++item_id_itr++) - StoreNewItemInBestSlot(item_id_itr->item_id, item_id_itr->item_amount); + StoreNewItemInBestSlots(item_id_itr->item_id, item_id_itr->item_amount); // bags and main-hand weapon must equipped at this moment // now second pass for not equipped (offhand weapon/shield if it attempt equipped before main-hand weapon) @@ -713,24 +713,30 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 return true; } -bool Player::StoreNewItemInBestSlot(uint32 titem_id, uint32 titem_amount) +bool Player::StoreNewItemInBestSlots(uint32 titem_id, uint32 titem_amount) { sLog.outDebug("STORAGE: Creating initial item, itemId = %u, count = %u",titem_id, titem_amount); - // attempt equip - uint16 eDest; - uint8 msg = CanEquipNewItem( NULL_SLOT, eDest, titem_id, titem_amount, false ); - if( msg == EQUIP_ERR_OK ) + // attempt equip by one + while(titem_amount > 0) { - EquipNewItem( eDest, titem_id, titem_amount, true); + uint16 eDest; + uint8 msg = CanEquipNewItem( NULL_SLOT, eDest, titem_id, false ); + if( msg != EQUIP_ERR_OK ) + break; + + EquipNewItem( eDest, titem_id, true); AutoUnequipOffhandIfNeed(); - return true; // equipped + --titem_amount; } + if(titem_amount == 0) + return true; // equipped + // attempt store ItemPosCountVec sDest; // store in main bag to simplify second pass (special bags can be not equipped yet at this moment) - msg = CanStoreNewItem( INVENTORY_SLOT_BAG_0, NULL_SLOT, sDest, titem_id, titem_amount ); + uint8 msg = CanStoreNewItem( INVENTORY_SLOT_BAG_0, NULL_SLOT, sDest, titem_id, titem_amount ); if( msg == EQUIP_ERR_OK ) { StoreNewItem( sDest, titem_id, true, Item::GenerateItemRandomPropertyId(titem_id) ); @@ -9307,10 +9313,10 @@ uint8 Player::CanStoreItems( Item **pItems,int count) const } ////////////////////////////////////////////////////////////////////////// -uint8 Player::CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, uint32 count, bool swap ) const +uint8 Player::CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, bool swap ) const { dest = 0; - Item *pItem = Item::CreateItem( item, count, this ); + Item *pItem = Item::CreateItem( item, 1, this ); if( pItem ) { uint8 result = CanEquipItem(slot, dest, pItem, swap ); @@ -9974,12 +9980,12 @@ Item* Player::_StoreItem( uint16 pos, Item *pItem, uint32 count, bool clone, boo } } -Item* Player::EquipNewItem( uint16 pos, uint32 item, uint32 count, bool update ) +Item* Player::EquipNewItem( uint16 pos, uint32 item, bool update ) { - Item *pItem = Item::CreateItem( item, count, this ); + Item *pItem = Item::CreateItem( item, 1, this ); if( pItem ) { - ItemAddedQuestCheck( item, count ); + ItemAddedQuestCheck( item, 1 ); Item * retItem = EquipItem( pos, pItem, update ); return retItem; @@ -16636,8 +16642,14 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint } else if( IsEquipmentPos( bag, slot ) ) { + if(pProto->BuyCount * count != 1) + { + SendEquipError( EQUIP_ERR_ITEM_CANT_BE_EQUIPPED, NULL, NULL ); + return false; + } + uint16 dest; - uint8 msg = CanEquipNewItem( slot, dest, item, pProto->BuyCount * count, false ); + uint8 msg = CanEquipNewItem( slot, dest, item, false ); if( msg != EQUIP_ERR_OK ) { SendEquipError( msg, NULL, NULL ); @@ -16659,7 +16671,7 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint } } - if(Item *it = EquipNewItem( dest, item, pProto->BuyCount * count, true )) + if(Item *it = EquipNewItem( dest, item, true )) { uint32 new_count = pCreature->UpdateVendorItemCurrentCount(crItem,pProto->BuyCount * count); diff --git a/src/game/Player.h b/src/game/Player.h index 89bc27b99..93ec74775 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1053,7 +1053,7 @@ class MANGOS_DLL_SPEC Player : public Unit } uint8 CanStoreItems( Item **pItem,int count) const; - uint8 CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, uint32 count, bool swap ) const; + uint8 CanEquipNewItem( uint8 slot, uint16 &dest, uint32 item, bool swap ) const; uint8 CanEquipItem( uint8 slot, uint16 &dest, Item *pItem, bool swap, bool not_loading = true ) const; uint8 CanUnequipItems( uint32 item, uint32 count ) const; uint8 CanUnequipItem( uint16 src, bool swap ) const; @@ -1064,10 +1064,10 @@ class MANGOS_DLL_SPEC Player : public Unit uint8 CanUseAmmo( uint32 item ) const; Item* StoreNewItem( ItemPosCountVec const& pos, uint32 item, bool update,int32 randomPropertyId = 0 ); Item* StoreItem( ItemPosCountVec const& pos, Item *pItem, bool update ); - Item* EquipNewItem( uint16 pos, uint32 item, uint32 count, bool update ); + Item* EquipNewItem( uint16 pos, uint32 item, bool update ); Item* EquipItem( uint16 pos, Item *pItem, bool update ); void AutoUnequipOffhandIfNeed(); - bool StoreNewItemInBestSlot(uint32 item_id, uint32 item_count); + bool StoreNewItemInBestSlots(uint32 item_id, uint32 item_count); 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; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 2d7234568..945fa5396 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6908" + #define REVISION_NR "6909" #endif // __REVISION_NR_H__ From 053d60a3f74bb5a70a5669e4018a19dbb0c221d0 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 15 Dec 2008 11:25:21 +0300 Subject: [PATCH 188/256] Added wotlk sql updates to mangos.sql --- sql/characters.sql | 67 +- sql/mangos.sql | 1245 +---------------- sql/wotlk_updates/6_character_achievement.sql | 4 +- 3 files changed, 108 insertions(+), 1208 deletions(-) diff --git a/sql/characters.sql b/sql/characters.sql index f73ca3c78..0dc980ebb 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -35,6 +35,28 @@ INSERT INTO `character_db_version` VALUES /*!40000 ALTER TABLE `character_db_version` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `account_data` +-- + +DROP TABLE IF EXISTS `account_data`; +CREATE TABLE `account_data` ( + `account` int(11) unsigned NOT NULL default '0', + `type` int(11) unsigned NOT NULL default '0', + `time` bigint(11) unsigned NOT NULL default '0', + `data` longtext NOT NULL, + PRIMARY KEY (`account`,`type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `account_data` +-- + +LOCK TABLES `account_data` WRITE; +/*!40000 ALTER TABLE `account_data` DISABLE KEYS */; +/*!40000 ALTER TABLE `account_data` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `arena_team` -- @@ -216,6 +238,47 @@ LOCK TABLES `characters` WRITE; /*!40000 ALTER TABLE `characters` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `character_achievement` +-- + +CREATE TABLE IF NOT EXISTS `character_achievement` ( + `guid` int(11) NOT NULL, + `achievement` int(11) NOT NULL, + `date` int(11) NOT NULL, + PRIMARY KEY (`guid`,`achievement`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_achievement` +-- + +LOCK TABLES `character_achievement` WRITE; +/*!40000 ALTER TABLE `character_achievement` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_achievement` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `character_achievement_progress` +-- + +CREATE TABLE IF NOT EXISTS `character_achievement_progress` ( + `guid` int(11) NOT NULL, + `criteria` int(11) NOT NULL, + `counter` int(11) NOT NULL, + `date` int(11) NOT NULL, + PRIMARY KEY (`guid`,`criteria`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +-- +-- Dumping data for table `character_achievement_progress` +-- + +LOCK TABLES `character_achievement_progress` WRITE; +/*!40000 ALTER TABLE `character_achievement_progress` DISABLE KEYS */; +/*!40000 ALTER TABLE `character_achievement_progress` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `character_action` -- @@ -398,9 +461,7 @@ CREATE TABLE `character_pet` ( `level` int(11) unsigned NOT NULL default '1', `exp` int(11) unsigned NOT NULL default '0', `Reactstate` tinyint(1) unsigned NOT NULL default '0', - `loyaltypoints` int(11) NOT NULL default '0', - `loyalty` int(11) unsigned NOT NULL default '0', - `trainpoint` int(11) NOT NULL default '0', + `talentpoints` int(11) unsigned NOT NULL default '0', `name` varchar(100) default 'Pet', `renamed` tinyint(1) unsigned NOT NULL default '0', `slot` int(11) unsigned NOT NULL default '0', diff --git a/sql/mangos.sql b/sql/mangos.sql index 2909816f3..d64e0c5d0 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -519,15 +519,9 @@ UNLOCK TABLES; DROP TABLE IF EXISTS `creature_equip_template`; CREATE TABLE `creature_equip_template` ( `entry` mediumint(8) unsigned NOT NULL default '0' COMMENT 'Unique entry', - `equipmodel1` mediumint(8) unsigned NOT NULL default '0', - `equipmodel2` mediumint(8) unsigned NOT NULL default '0', - `equipmodel3` mediumint(8) unsigned NOT NULL default '0', - `equipinfo1` int(10) unsigned NOT NULL default '0', - `equipinfo2` int(10) unsigned NOT NULL default '0', - `equipinfo3` int(10) unsigned NOT NULL default '0', - `equipslot1` int(11) NOT NULL default '0', - `equipslot2` int(11) NOT NULL default '0', - `equipslot3` int(11) NOT NULL default '0', + `equipentry1` mediumint(8) unsigned NOT NULL default '0', + `equipentry2` mediumint(8) unsigned NOT NULL default '0', + `equipentry3` mediumint(8) unsigned NOT NULL default '0', PRIMARY KEY (`entry`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Creature System (Equipment)'; @@ -1547,6 +1541,7 @@ CREATE TABLE `item_template` ( `maxcount` smallint(5) unsigned NOT NULL default '0', `stackable` smallint(5) unsigned NOT NULL default '1', `ContainerSlots` tinyint(3) unsigned NOT NULL default '0', + `StatsCount` tinyint(3) unsigned NOT NULL default '0', `stat_type1` tinyint(3) unsigned NOT NULL default '0', `stat_value1` smallint(6) NOT NULL default '0', `stat_type2` tinyint(3) unsigned NOT NULL default '0', @@ -1567,6 +1562,8 @@ CREATE TABLE `item_template` ( `stat_value9` smallint(6) NOT NULL default '0', `stat_type10` tinyint(3) unsigned NOT NULL default '0', `stat_value10` smallint(6) NOT NULL default '0', + `ScalingStatDistribution` smallint(6) NOT NULL default '0', + `ScalingStatValue` smallint(6) NOT NULL default '0', `dmg_min1` float NOT NULL default '0', `dmg_max1` float NOT NULL default '0', `dmg_type1` tinyint(3) unsigned NOT NULL default '0', @@ -1655,12 +1652,13 @@ CREATE TABLE `item_template` ( `GemProperties` mediumint(9) NOT NULL default '0', `RequiredDisenchantSkill` smallint(6) NOT NULL default '-1', `ArmorDamageModifier` float NOT NULL default '0', + `Duration` int(11) NOT NULL default '0' COMMENT 'Duration in seconds. Negative value means realtime, postive value ingame time', + `ItemLimitCategory` smallint(6) NOT NULL default '0', `ScriptName` varchar(64) NOT NULL default '', `DisenchantID` mediumint(8) unsigned NOT NULL default '0', `FoodType` tinyint(3) unsigned NOT NULL default '0', `minMoneyLoot` int(10) unsigned NOT NULL default '0', `maxMoneyLoot` int(10) unsigned NOT NULL default '0', - `Duration` int(11) NOT NULL default '0' COMMENT 'Duration in seconds. Negative value means realtime, postive value ingame time', PRIMARY KEY (`entry`), KEY `items_index` (`class`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Item System'; @@ -2462,6 +2460,8 @@ INSERT INTO `mangos_string` VALUES (342,'%s is now not following you.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (343,'Creature (Entry: %u) cannot be tamed.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (344,'You already have pet.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(345,'Forced customize for player %s will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(346,'Forced customize for player %s (GUID #%u) will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (400,'|cffff0000[System Message]:|rScripts reloaded',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (401,'You change security level of account %s to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (402,'%s changed your security level to %i.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), @@ -2757,6 +2757,33 @@ INSERT INTO `mangos_string` VALUES /*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `milling_loot_template` +-- + +DROP TABLE IF EXISTS `milling_loot_template`; +CREATE TABLE `milling_loot_template` ( + `entry` mediumint(8) unsigned NOT NULL default '0', + `item` mediumint(8) unsigned NOT NULL default '0', + `ChanceOrQuestChance` float NOT NULL default '100', + `groupid` tinyint(3) unsigned NOT NULL default '0', + `mincountOrRef` mediumint(9) NOT NULL default '1', + `maxcount` tinyint(3) unsigned NOT NULL default '1', + `lootcondition` tinyint(3) unsigned NOT NULL default '0', + `condition_value1` mediumint(8) unsigned NOT NULL default '0', + `condition_value2` mediumint(8) unsigned NOT NULL default '0', + PRIMARY KEY (`entry`,`item`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; + +-- +-- Dumping data for table `milling_loot_template` +-- + +LOCK TABLES `milling_loot_template` WRITE; +/*!40000 ALTER TABLE `milling_loot_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `milling_loot_template` ENABLE KEYS */; +UNLOCK TABLES; + -- -- Table structure for table `npc_gossip` -- @@ -10409,6 +10436,8 @@ CREATE TABLE `quest_template` ( `QuestFlags` smallint(5) unsigned NOT NULL default '0', `SpecialFlags` tinyint(3) unsigned NOT NULL default '0', `CharTitleId` tinyint(3) unsigned NOT NULL default '0', + `PlayersSlain` tinyint(3) unsigned NOT NULL default '0', + `BonusTalents` tinyint(3) unsigned NOT NULL default '0', `PrevQuestId` mediumint(9) NOT NULL default '0', `NextQuestId` mediumint(9) NOT NULL default '0', `ExclusiveGroup` mediumint(9) NOT NULL default '0', @@ -10666,7 +10695,9 @@ DROP TABLE IF EXISTS `spell_affect`; CREATE TABLE `spell_affect` ( `entry` smallint(5) unsigned NOT NULL default '0', `effectId` tinyint(3) unsigned NOT NULL default '0', - `SpellFamilyMask` bigint(20) unsigned NOT NULL default '0', + `SpellClassMask0` int(5) unsigned NOT NULL default '0', + `SpellClassMask1` int(5) unsigned NOT NULL default '0', + `SpellClassMask2` int(5) unsigned NOT NULL default '0', PRIMARY KEY (`entry`,`effectId`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; @@ -10676,1198 +10707,6 @@ CREATE TABLE `spell_affect` ( LOCK TABLES `spell_affect` WRITE; /*!40000 ALTER TABLE `spell_affect` DISABLE KEYS */; -INSERT INTO `spell_affect` VALUES -(5420,2,0x00001012100000D0), -(8875,1,0x0000040000000000), -(11069,0,0x0000000000000001), -(11070,0,0x0000000000000020), -(11071,0,0x0000000000100000), -(11083,0,0x0000000000C20017), -(11124,0,0x0000000008C20017), -(11151,0,0x00000000000202E0), -(11160,0,0x00000001020203E0), -(11175,1,0x0000000000100000), -(11207,0,0x00000000000202E0), -(11222,0,0x0000000020001800), -(11242,0,0x0000000020001000), -(11247,0,0x0000000000002000), -(12042,0,0x0000000020E01AF7), -(12042,1,0x0000000020E01AF7), -(12042,2,0x0000000020E01AF7), -(12043,0,0x0000000021400035), -(12285,0,0x0000000000000001), -(12286,0,0x0000000000000020), -(12287,1,0x0000000000000080), -(12295,1,0x0000000002000000), -(12295,2,0x0000040000000000), -(12301,0,0x0000000000000100), -(12303,1,0x0000100000000000), -(12308,0,0x0000000000004000), -(12318,0,0x0000008000010000), -(12321,0,0x0000008000030000), -(12321,1,0x0000008000030000), -(12330,0,0x0000000000200000), -(12338,0,0x0000000000000001), -(12339,0,0x0000000000000001), -(12340,0,0x0000000000000001), -(12341,0,0x0000000000000001), -(12351,0,0x0000000000C20017), -(12378,0,0x0000000008C20017), -(12398,0,0x0000000008C20017), -(12399,0,0x0000000008C20017), -(12400,0,0x0000000008C20017), -(12467,0,0x0000000020001000), -(12469,0,0x0000000020001000), -(12472,1,0x00000000E44008A5), -(12473,0,0x0000000000000020), -(12496,0,0x0000000000100000), -(12497,0,0x0000000000100000), -(12518,0,0x00000001020203E0), -(12519,0,0x00000001020203E0), -(12536,0,0x0000000020C01AF7), -(12569,1,0x0000000000100000), -(12571,1,0x0000000000100000), -(12658,0,0x0000000000000020), -(12659,0,0x0000000000000020), -(12665,1,0x0000000000000080), -(12666,1,0x0000000000000080), -(12672,0,0x00000000000202E0), -(12676,1,0x0000000002000000), -(12676,2,0x0000040000000000), -(12677,1,0x0000000002000000), -(12677,2,0x0000040000000000), -(12697,0,0x0000000000000001), -(12788,1,0x0000100000000000), -(12789,1,0x0000100000000000), -(12810,0,0x0000000000004000), -(12811,0,0x0000000000004000), -(12818,0,0x0000000000000100), -(12835,0,0x0000008000030000), -(12835,1,0x0000008000030000), -(12836,0,0x0000008000030000), -(12836,1,0x0000008000030000), -(12837,0,0x0000008000030000), -(12837,1,0x0000008000030000), -(12838,0,0x0000008000030000), -(12838,1,0x0000008000030000), -(12839,0,0x0000000020001800), -(12840,0,0x0000000020001800), -(12841,0,0x0000000020001800), -(12842,0,0x0000000020001800), -(12857,0,0x0000008000010000), -(12858,0,0x0000008000010000), -(12860,0,0x0000008000010000), -(12861,0,0x0000008000010000), -(12862,0,0x0000000000200000), -(12945,1,0x0000000000001000), -(12952,0,0x00000000000202E0), -(12953,0,0x00000000000202E0), -(12954,0,0x00000000000202E0), -(12957,0,0x00000000000202E0), -(13733,0,0x0000000000000004), -(13733,1,0x0000000400000000), -(13742,0,0x0000000000000060), -(13743,0,0x0000000000000040), -(13865,0,0x0000000000000004), -(13865,1,0x0000000400000000), -(13866,0,0x0000000000000004), -(13866,1,0x0000000400000000), -(13872,0,0x0000000000000060), -(13875,0,0x0000000000000040), -(13975,0,0x0000000000400000), -(13975,1,0x0000000000400000), -(13976,0,0x0000000000000700), -(13979,0,0x0000000000000700), -(13980,0,0x0000000000000700), -(13981,0,0x0000000001000000), -(13981,1,0x0000000000000800), -(14057,0,0x0000000600000304), -(14062,0,0x0000000000400000), -(14062,1,0x0000000000400000), -(14063,0,0x0000000000400000), -(14063,1,0x0000000000400000), -(14064,0,0x0000000000400000), -(14064,1,0x0000000000400000), -(14065,0,0x0000000000400000), -(14065,1,0x0000000000400000), -(14066,0,0x0000000001000000), -(14066,1,0x0000000000000800), -(14072,0,0x0000000600000304), -(14073,0,0x0000000600000304), -(14074,0,0x0000000600000304), -(14075,0,0x0000000600000304), -(14076,0,0x0000000001000080), -(14076,1,0x0000000001000080), -(14082,0,0x0000000000000500), -(14083,0,0x0000000000000500), -(14094,0,0x0000000001000080), -(14094,1,0x0000000001000080), -(14113,0,0x000000000001E000), -(14114,0,0x000000000001E000), -(14115,0,0x000000000001E000), -(14116,0,0x000000000001E000), -(14117,0,0x000000000001E000), -(14128,0,0x000000062600000E), -(14132,0,0x000000062600000E), -(14135,0,0x000000062600000E), -(14136,0,0x000000062600000E), -(14137,0,0x000000062600000E), -(14143,0,0x0000000004000206), -(14149,0,0x0000000004000206), -(14162,0,0x0000000000020000), -(14163,0,0x0000000000020000), -(14164,0,0x0000000000020000), -(14168,0,0x0000000000080000), -(14169,0,0x0000000000080000), -(14174,0,0x0000000000200000), -(14175,0,0x0000000000200000), -(14176,0,0x0000000000200000), -(14177,0,0x0000000C6012031E), -(14179,0,0x00000009003E0000), -(14520,0,0x00000963BF61C16F), -(14523,1,0x000000208030016B), -(14523,2,0x000000208030016B), -(14743,0,0x0000049440963E90), -(14747,0,0x0000000000000002), -(14750,0,0x0000000000000010), -(14751,0,0xFFFFFFFFFFFFFFFF), -(14751,1,0xFFFFFFFFFFFFFFFF), -(14770,0,0x0000000000000002), -(14771,0,0x0000000000000002), -(14772,0,0x0000000000000010), -(14780,0,0x00000963BF61C16F), -(14781,0,0x00000963BF61C16F), -(14782,0,0x00000963BF61C16F), -(14783,0,0x00000963BF61C16F), -(14784,1,0x000000208030016B), -(14784,2,0x000000208030016B), -(14785,1,0x000000208030016B), -(14785,2,0x000000208030016B), -(14786,1,0x000000208030016B), -(14786,2,0x000000208030016B), -(14787,1,0x000000208030016B), -(14787,2,0x000000208030016B), -(14908,0,0x0000000000000040), -(14909,1,0x0000000000100080), -(14911,0,0x0000002000000200), -(14912,0,0x0000000000041400), -(14913,0,0x0000000400041E00), -(15012,0,0x0000000400041E00), -(15013,0,0x0000000000041400), -(15014,0,0x0000000000041400), -(15017,1,0x0000000000100080), -(15018,0,0x0000002000000200), -(15020,0,0x0000000000000040), -(15047,0,0x00000000000202E0), -(15052,0,0x00000000000202E0), -(15053,0,0x00000000000202E0), -(15257,0,0x000004020288A010), -(15259,0,0x0000000202002000), -(15259,1,0x0000040000808000), -(15260,0,0x00000442068BA000), -(15272,0,0x00000D4A068BE104), -(15307,0,0x0000000202002000), -(15307,1,0x0000040000808000), -(15308,0,0x0000000202002000), -(15308,1,0x0000040000808000), -(15309,0,0x0000000202002000), -(15309,1,0x0000040000808000), -(15310,0,0x0000000202002000), -(15310,1,0x0000040000808000), -(15318,0,0x00000D4A068BE104), -(15320,0,0x00000D4A068BE104), -(15327,0,0x00000442068BA000), -(15328,0,0x00000442068BA000), -(15329,0,0x00000442068BA000), -(15330,0,0x00000442068BA000), -(15331,0,0x000004020288A010), -(15332,0,0x000004020288A010), -(15333,0,0x000004020288A010), -(15334,0,0x000004020288A010), -(16035,0,0x0000000090100003), -(16038,0,0x0000000040000000), -(16039,0,0x0000000090100003), -(16041,0,0x0000000000000003), -(16043,0,0x0000000000000008), -(16043,1,0x0000000100000000), -(16086,0,0x0000000000000020), -(16086,1,0x0000000000000020), -(16086,2,0x0000000000000004), -(16089,0,0x00000004D3300407), -(16105,0,0x0000000090100003), -(16106,0,0x0000000090100003), -(16106,1,0x0000000090100003), -(16107,0,0x0000000090100003), -(16108,0,0x0000000090100003), -(16109,0,0x0000000090100003), -(16110,0,0x0000000090100003), -(16111,0,0x0000000090100003), -(16112,0,0x0000000090100003), -(16117,0,0x0000000000000003), -(16118,0,0x0000000000000003), -(16119,0,0x0000000000000003), -(16120,0,0x0000000000000003), -(16130,0,0x0000000000000008), -(16130,1,0x0000000100000000), -(16160,0,0x0000000040000000), -(16161,0,0x0000000040000000), -(16166,0,0x0000000090100003), -(16166,1,0x0000000090100003), -(16173,0,0x0000000020081018), -(16179,0,0x00000000000000C0), -(16181,0,0x00000000000001C0), -(16184,0,0x0000000000000200), -(16184,1,0x0000000000000200), -(16187,0,0x0000000000006000), -(16187,1,0x0000000000006000), -(16188,0,0x00000000000009C3), -(16189,0,0x000001000403E000), -(16205,0,0x0000000000006000), -(16205,1,0x0000000000006000), -(16206,0,0x0000000000006000), -(16206,1,0x0000000000006000), -(16207,0,0x0000000000006000), -(16207,1,0x0000000000006000), -(16208,0,0x0000000000006000), -(16208,1,0x0000000000006000), -(16209,1,0x0000000000000200), -(16214,0,0x00000000000000C0), -(16215,0,0x00000000000000C0), -(16216,0,0x00000000000000C0), -(16217,0,0x00000000000000C0), -(16222,0,0x0000000020081018), -(16223,0,0x0000000020081018), -(16224,0,0x0000000020081018), -(16225,0,0x0000000020081018), -(16230,0,0x00000000000001C0), -(16232,0,0x00000000000001C0), -(16233,0,0x00000000000001C0), -(16234,0,0x00000000000001C0), -(16246,0,0x0000000090100003), -(16258,0,0x0000000000008000), -(16258,1,0x0000000000040000), -(16259,0,0x0000000000010000), -(16259,1,0x0000000000020000), -(16261,0,0x0000000000000400), -(16266,0,0x0000000000400000), -(16266,1,0x0000000001000000), -(16266,2,0x0000000000800000), -(16290,0,0x0000000000000400), -(16291,0,0x0000000000000400), -(16293,0,0x0000000000008000), -(16293,1,0x0000000000040000), -(16295,0,0x0000000000010000), -(16295,1,0x0000000000020000), -(16493,0,0x0000014D2A600CEF), -(16494,0,0x0000014D2A600CEF), -(16513,0,0x000000080001E000), -(16513,1,0x000000000001E000), -(16513,2,0x000000000001E000), -(16514,0,0x000000080001E000), -(16514,1,0x000000000001E000), -(16514,2,0x000000000001E000), -(16515,0,0x000000080001E000), -(16515,1,0x000000000001E000), -(16515,2,0x000000000001E000), -(16544,2,0x0000000000000004), -(16578,0,0x0000000000000003), -(16579,0,0x0000000000000003), -(16580,0,0x0000000000000003), -(16581,0,0x0000000000000003), -(16582,0,0x0000000000000003), -(16719,0,0x000000080001E000), -(16719,1,0x000000000001E000), -(16719,2,0x000000000001E000), -(16720,0,0x000000080001E000), -(16720,1,0x000000000001E000), -(16720,2,0x000000000001E000), -(16757,0,0x00000000000200A0), -(16757,1,0x0000000000000240), -(16758,0,0x00000000000200A0), -(16758,1,0x0000000000000240), -(16763,0,0x0000000000000020), -(16765,0,0x0000000000000020), -(16766,0,0x0000000000000020), -(16814,0,0x0000000000000005), -(16815,0,0x0000000000000005), -(16816,0,0x0000000000000005), -(16817,0,0x0000000000000005), -(16818,0,0x0000000000000005), -(16819,0,0x0002122000600707), -(16820,0,0x0002122000600707), -(16821,0,0x0000000000000002), -(16821,1,0x0000000000000002), -(16821,2,0x0000000000000002), -(16822,0,0x0000000000000002), -(16822,1,0x0000000000000002), -(16822,2,0x0000000000000002), -(16833,0,0x0000E000E2000000), -(16834,0,0x0000E000E2000000), -(16835,0,0x0000E000E2000000), -(16836,1,0x0000000000000300), -(16839,1,0x0000000000000300), -(16840,1,0x0000000000000300), -(16850,1,0x0000000000000001), -(16870,0,0x001007F100E3FEFF), -(16886,0,0x0000000001000265), -(16896,0,0x0000000000000007), -(16896,1,0x0000000000000007), -(16897,0,0x0000000000000007), -(16897,1,0x0000000000000007), -(16899,0,0x0000000000000007), -(16899,1,0x0000000000000007), -(16900,0,0x0000000000000007), -(16900,1,0x0000000000000007), -(16901,0,0x0000000000000007), -(16901,1,0x0000000000000007), -(16918,0,0x0000002000000200), -(16919,0,0x0000002000000200), -(16920,0,0x0000002000000200), -(16923,1,0x0000000000000001), -(16924,1,0x0000000000000001), -(16934,0,0x0010004000000800), -(16934,1,0x0000040000001000), -(16935,0,0x0010004000000800), -(16935,1,0x0000040000001000), -(16936,0,0x0010004000000800), -(16936,1,0x0000040000001000), -(16937,0,0x0010004000000800), -(16937,1,0x0000040000001000), -(16938,0,0x0010004000000800), -(16938,1,0x0000040000001000), -(16947,1,0x0000000002000000), -(16948,1,0x0000000002000000), -(16949,1,0x0000000002000000), -(16966,0,0x0000000000008000), -(16966,1,0x0000010000000000), -(16968,0,0x0000000000008000), -(16968,1,0x0000010000000000), -(16998,0,0x0000000000001000), -(16998,2,0x0000000000001000), -(16999,0,0x0000000000001000), -(16999,2,0x0000000000001000), -(17104,0,0x00000010000000F0), -(17104,1,0x00000010000000F0), -(17111,0,0x0000000000000010), -(17112,0,0x0000000000000010), -(17113,0,0x0000000000000010), -(17114,0,0x0000000000000010), -(17115,0,0x0000000000000010), -(17116,0,0x0002002010000261), -(17118,0,0x001005D000E193F7), -(17118,1,0x0004103000340750), -(17119,0,0x001005D000E193F7), -(17119,1,0x0004103000340750), -(17120,0,0x001005D000E193F7), -(17120,1,0x0004103000340750), -(17121,0,0x001005D000E193F7), -(17121,1,0x0004103000340750), -(17122,0,0x001005D000E193F7), -(17122,1,0x0004103000340750), -(17123,0,0x0000000000000080), -(17124,0,0x0000000000000080), -(17191,0,0x0000000000000040), -(17322,0,0x00000542068AA004), -(17323,0,0x00000542068AA004), -(17768,0,0x0000000040000000), -(17768,1,0x0000000080000000), -(17778,0,0x000010C0000003E5), -(17779,0,0x000010C0000003E5), -(17780,0,0x000010C0000003E5), -(17781,0,0x000010C0000003E5), -(17782,0,0x000010C0000003E5), -(17788,1,0x0000008000000000), -(17789,1,0x0000008000000000), -(17790,1,0x0000008000000000), -(17791,1,0x0000008000000000), -(17792,1,0x0000008000000000), -(17904,0,0x0000000000000000), -(17912,0,0x0000000000000000), -(17913,0,0x0000000000000000), -(17914,0,0x0000000000000000), -(17915,0,0x0000000000000000), -(17916,0,0x0000000000000000), -(17917,0,0x000010C0000003A5), -(17917,1,0x000010C0000003E5), -(17918,0,0x000010C0000003A5), -(17918,1,0x000010C0000003E5), -(17927,0,0x0000000000000100), -(17929,0,0x0000000000000100), -(17930,0,0x0000000000000100), -(17941,0,0x0000000000000001), -(17954,0,0x000000C000001364), -(17954,1,0x000000C000001364), -(17954,2,0x0000004000000000), -(17955,0,0x000000C000001364), -(17955,1,0x000000C000001364), -(17955,2,0x0000004000000000), -(17956,0,0x000000C000001364), -(17956,1,0x000000C000001364), -(17956,2,0x0000004000000000), -(17957,0,0x000000C000001364), -(17957,1,0x000000C000001364), -(17957,2,0x0000004000000000), -(17958,0,0x000000C000001364), -(17958,1,0x000000C000001364), -(17958,2,0x0000004000000000), -(17959,0,0x000010C0000003E5), -(18126,0,0x0000000000001000), -(18127,0,0x0000000000001000), -(18130,0,0x000010C0000003E5), -(18131,0,0x000010C0000003E5), -(18132,0,0x000010C0000003E5), -(18133,0,0x000010C0000003E5), -(18134,0,0x000010C0000003E5), -(18135,0,0x000010C0000003E5), -(18136,0,0x000010C0000003E5), -(18174,0,0x0000071B804CC41A), -(18175,0,0x0000071B804CC41A), -(18176,0,0x0000071B804CC41A), -(18177,0,0x0000071B804CC41A), -(18178,0,0x0000071B804CC41A), -(18179,0,0x0000000000008000), -(18180,0,0x0000000000008000), -(18213,0,0x0000000000004000), -(18213,1,0x0000871B804CC41A), -(18218,0,0x000007138048C41A), -(18219,0,0x000007138048C41A), -(18271,0,0x000011130008A48B), -(18271,1,0x000011130008A48B), -(18272,0,0x000011130008A48B), -(18272,1,0x000011130008A48B), -(18273,0,0x000011130008A48B), -(18273,1,0x000011130008A48B), -(18274,0,0x000011130008A48B), -(18274,1,0x000011130008A48B), -(18275,0,0x000011130008A48B), -(18275,1,0x000011130008A48B), -(18288,0,0x0000000200000400), -(18288,1,0x0000000000400000), -(18372,1,0x0000871B804CC41A), -(18427,0,0x0000000000020006), -(18428,0,0x0000000000020006), -(18429,0,0x0000000000020006), -(18544,0,0x0000041202F8A090), -(18544,1,0x0000001202582090), -(18544,2,0x0000040000A08000), -(18547,0,0x0000041202F8A090), -(18547,1,0x0000001202582090), -(18547,2,0x0000040000A08000), -(18548,0,0x0000041202F8A090), -(18548,1,0x0000001202582090), -(18548,2,0x0000040000A08000), -(18549,0,0x0000041202F8A090), -(18549,1,0x0000001202582090), -(18549,2,0x0000040000A08000), -(18550,0,0x0000041202F8A090), -(18550,1,0x0000001202582090), -(18550,2,0x0000040000A08000), -(18703,1,0x0000000001000000), -(18704,1,0x0000000001000000), -(18731,0,0x0000000010000000), -(18743,0,0x0000000010000000), -(18744,0,0x0000000010000000), -(18748,0,0x0000000008000000), -(18749,0,0x0000000008000000), -(18750,0,0x0000000008000000), -(18767,1,0x0000000000020000), -(18768,1,0x0000000000020000), -(18821,0,0x0000000000000800), -(18821,1,0x0000000000000800), -(18821,2,0x0000000000000800), -(18822,0,0x0000000000000800), -(18822,1,0x0000000000000800), -(18822,2,0x0000000000000800), -(18827,0,0x0000000000000400), -(18829,0,0x0000000000000400), -(19239,0,0x0000000000000018), -(19239,1,0x0000000000000004), -(19245,0,0x0000000000000018), -(19245,1,0x0000200000000004), -(19416,0,0x000210810007FA00), -(19417,0,0x000210810007FA00), -(19418,0,0x000210810007FA00), -(19419,0,0x000210810007FA00), -(19420,0,0x000210810007FA00), -(19461,0,0x0000000000003000), -(19461,1,0x0000000000003000), -(19462,0,0x0000000000003000), -(19462,1,0x0000000000003000), -(19464,0,0x0000010000004000), -(19464,1,0x0000008000000000), -(19464,2,0x000011800000C000), -(19465,0,0x0000010000004000), -(19465,1,0x0000008000000000), -(19465,2,0x000011800000C000), -(19466,0,0x0000010000004000), -(19466,1,0x0000008000000000), -(19466,2,0x000011800000C000), -(19467,0,0x0000010000004000), -(19467,1,0x0000008000000000), -(19467,2,0x000011800000C000), -(19468,0,0x0000010000004000), -(19468,1,0x0000008000000000), -(19468,2,0x000011800000C000), -(19485,0,0x0000000100061801), -(19487,0,0x0000000100061801), -(19488,0,0x0000000100061801), -(19489,0,0x0000000100061801), -(19490,0,0x0000000100061801), -(19498,0,0x000210810007FA01), -(19499,0,0x000210810007FA01), -(19500,0,0x000210810007FA01), -(19549,0,0x0000000000080000), -(19550,0,0x0000000000080000), -(19551,0,0x0000000000080000), -(19552,0,0x0000000000100000), -(19552,1,0x0000020000000000), -(19553,0,0x0000000000100000), -(19553,1,0x0000020000000000), -(19554,0,0x0000000000100000), -(19554,1,0x0000020000000000), -(19555,0,0x0000000000100000), -(19555,1,0x0000020000000000), -(19556,0,0x0000000000100000), -(19556,1,0x0000020000000000), -(19559,0,0x0000000000200000), -(19560,0,0x0000000000200000), -(19572,1,0x0000000000800000), -(19573,1,0x0000000000800000), -(19583,0,0x0000000008000000), -(19584,0,0x0000000008000000), -(19585,0,0x0000000008000000), -(19586,0,0x0000000008000000), -(19587,0,0x0000000008000000), -(19590,0,0x0000000020000000), -(19592,0,0x0000000020000000), -(19598,0,0x0000000040000000), -(19599,0,0x0000000040000000), -(19600,0,0x0000000040000000), -(19601,0,0x0000000040000000), -(19602,0,0x0000000040000000), -(19609,0,0x0000000004000000), -(19610,0,0x0000000004000000), -(19612,0,0x0000000004000000), -(20101,0,0x000004000A000200), -(20102,0,0x000004000A000200), -(20103,0,0x000004000A000200), -(20104,0,0x000004000A000200), -(20105,0,0x000004000A000200), -(20138,0,0x0000000000000040), -(20139,0,0x0000000000000040), -(20140,0,0x0000000000000040), -(20141,0,0x0000000000000040), -(20142,0,0x0000000000000040), -(20174,0,0x0000000000000080), -(20174,1,0x0000000000000010), -(20175,0,0x0000000000000080), -(20175,1,0x0000000000000010), -(20216,0,0x00010000C0200000), -(20224,0,0x0000000008000400), -(20225,0,0x0000000008000400), -(20237,0,0x00000000C0000000), -(20238,0,0x00000000C0000000), -(20239,0,0x00000000C0000000), -(20249,0,0x0000000040000000), -(20250,0,0x0000000040000000), -(20251,0,0x0000000040000000), -(20254,0,0x0000000000020000), -(20254,1,0x0000000000020000), -(20254,2,0x0000000000020000), -(20255,0,0x0000000000020000), -(20255,1,0x0000000000020000), -(20255,2,0x0000000000020000), -(20256,0,0x0000000000020000), -(20256,1,0x0000000000020000), -(20256,2,0x0000000000020000), -(20330,0,0x0000000008000400), -(20331,0,0x0000000008000400), -(20332,0,0x0000000008000400), -(20335,0,0x0000000020000000), -(20336,0,0x0000000020000000), -(20337,0,0x0000000020000000), -(20359,0,0x0000000080000000), -(20360,0,0x0000000080000000), -(20361,0,0x0000000080000000), -(20468,1,0x0000000000000001), -(20469,1,0x0000000000000001), -(20470,1,0x0000000000000001), -(20575,0,0x0000000004000000), -(20575,1,0x0000000004000000), -(20576,0,0x0000000002000000), -(21873,0,0x0000E000E2000000), -(21881,0,0x000000000001E000), -(21887,0,0x0000036C2A764EEF), -(21895,0,0x000000000403E000), -(21899,0,0x0000000000000100), -(21942,1,0x0000000008000000), -(22008,0,0x0000000021400035), -(23025,0,0x0000000000010000), -(23047,0,0x0000040000000000), -(23047,1,0x0000040000000000), -(23158,0,0x0000000000000200), -(23300,0,0x0000000020000000), -(23555,0,0x000010C0000003E5), -(23561,0,0x0000000000004000), -(23566,0,0x0000000000001000), -(23724,0,0x0000E000E2000000), -(23726,0,0x0000000000002000), -(23726,1,0x0000000000010000), -(24348,0,0x0000000000200000), -(24429,0,0x0000000000004000), -(24431,0,0x0000000400000000), -(24460,0,0x0000000010000180), -(24469,0,0x0000000001000000), -(24499,0,0x0000000000000400), -(24542,1,0x00000000000000F0), -(24546,1,0x0000000400041E00), -(24691,0,0x0000000000003000), -(24691,1,0x0000000000003000), -(24943,0,0x00000010000000F0), -(24943,1,0x00000010000000F0), -(24944,0,0x00000010000000F0), -(24944,1,0x00000010000000F0), -(24945,0,0x00000010000000F0), -(24945,1,0x00000010000000F0), -(24946,0,0x00000010000000F0), -(24946,1,0x00000010000000F0), -(26106,0,0x0000000010000000), -(26109,0,0x00000080000F0000), -(26112,0,0x0000000000000020), -(26118,0,0x0000000004000000), -(26118,1,0x0000000004000000), -(26174,0,0x0000000000000020), -(27789,1,0x0000000010400200), -(27790,1,0x0000000010400200), -(27828,0,0x0000049440963E90), -(27846,0,0x0000000000000020), -(27850,0,0x0000000000000040), -(27851,0,0x0000000000001000), -(28088,0,0x000000000001E000), -(28107,0,0x0000000000040000), -(28539,0,0x0000000000001000), -(28682,0,0x0000004008C20017), -(28743,0,0x00000000000000F0), -(28746,1,0x0000000100000406), -(28751,0,0x0000000000021000), -(28755,0,0x0000000000000020), -(28763,0,0x0000000004000000), -(28774,0,0x0000000000008000), -(28775,0,0x0000000100000000), -(28787,0,0x0000000000001000), -(28807,0,0x0000000000000040), -(28808,0,0x0000000411041E40), -(28811,0,0x0000000002020006), -(28814,0,0x0000000000020000), -(28815,0,0x0000000002000006), -(28818,0,0x0000000020081018), -(28821,0,0x0000000000000400), -(28829,0,0x0000000000000002), -(28831,0,0x0000000000000001), -(28842,0,0x0000000100004440), -(28843,0,0x0000000000088000), -(28844,0,0x0000000000000400), -(28852,0,0x0000000000000200), -(28852,1,0x0000000020000000), -(28855,0,0x0000000000000800), -(28855,1,0x0010000000000000), -(28999,0,0x0000000000000003), -(29000,0,0x0000000000000003), -(29005,0,0x0000000090100003), -(29063,0,0x00000000000009C3), -(29079,0,0x0000000000400000), -(29079,1,0x0000000001000000), -(29079,2,0x0000000000800000), -(29080,0,0x0000000000400000), -(29080,1,0x0000000001000000), -(29080,2,0x0000000000800000), -(29171,0,0x0000000000004000), -(29187,0,0x00000000000001C0), -(29187,1,0x0004103000340750), -(29189,0,0x00000000000001C0), -(29189,1,0x0004103000340750), -(29191,0,0x00000000000001C0), -(29191,1,0x0004103000340750), -(29202,0,0x0000000000000040), -(29205,0,0x0000000000000040), -(29206,0,0x0000000000000040), -(29438,0,0x0000000000D000D7), -(29439,0,0x0000000000D000D7), -(29440,0,0x0000000000D000D7), -(29721,0,0x0000000400000000), -(29723,0,0x0000000800002010), -(29723,1,0x0000000800002010), -(29724,0,0x0000000800002010), -(29724,1,0x0000000800002010), -(29725,0,0x0000000800002010), -(29725,1,0x0000000800002010), -(29759,1,0x0000075D6E6ECEEF), -(29760,1,0x0000075D6E6ECEEF), -(29761,1,0x0000075D6E6ECEEF), -(29762,1,0x0000075D6E6ECEEF), -(29763,1,0x0000075D6E6ECEEF), -(29776,0,0x0000000400000000), -(29787,0,0x0000036C2A764EEF), -(29790,0,0x0000036C2A764EEF), -(29792,0,0x0000036C2A764EEF), -(29836,0,0x0000001000000020), -(29859,0,0x0000001000000020), -(29888,0,0x0000000040000000), -(29889,0,0x0000000040000000), -(29976,0,0x0000000021400035), -(30049,0,0x0000000000080000), -(30051,0,0x0000000000080000), -(30052,0,0x0000000000080000), -(30054,0,0x0000000800000000), -(30057,0,0x0000000800000000), -(30060,0,0x0000001000000402), -(30060,1,0x0000001000000402), -(30060,2,0x0000871B804CC41A), -(30061,0,0x0000001000000402), -(30061,1,0x0000001000000402), -(30061,2,0x0000871B804CC41A), -(30062,0,0x0000001000000402), -(30062,1,0x0000001000000402), -(30062,2,0x0000871B804CC41A), -(30063,0,0x0000001000000402), -(30063,1,0x0000001000000402), -(30063,2,0x0000871B804CC41A), -(30064,0,0x0000001000000402), -(30064,1,0x0000001000000402), -(30064,2,0x0000871B804CC41A), -(30085,0,0x0000071B804CC41A), -(30085,1,0x0000000000000400), -(30085,2,0x0000000000000002), -(30086,0,0x0000071B804CC41A), -(30086,1,0x0000000000000400), -(30086,2,0x0000000000000002), -(30017,0,0x0000000000000000), -(30143,0,0x0000002000000000), -(30144,0,0x0000002000000000), -(30145,0,0x0000002000000000), -(30242,0,0x0000200000000000), -(30245,0,0x0000200000000000), -(30246,0,0x0000200000000000), -(30247,0,0x0000200000000000), -(30248,0,0x0000200000000000), -(30251,0,0x000010C000000125), -(30256,0,0x000010C000000125), -(30280,0,0x0000000000000000), -(30288,0,0x0000004000000001), -(30289,0,0x0000004000000001), -(30290,0,0x0000004000000001), -(30291,0,0x0000004000000001), -(30292,0,0x0000004000000001), -(30319,1,0x0000400000000000), -(30320,1,0x0000400000000000), -(30321,1,0x0000400000000000), -(30326,0,0x0000000000040010), -(30327,0,0x0000000000040010), -(30328,0,0x0000000000040010), -(30812,0,0x00000C78B018141B), -(30813,0,0x00000C78B018141B), -(30814,0,0x00000C78B018141B), -(30872,0,0x0000000000000100), -(30873,0,0x0000000000000100), -(30892,0,0x0000000008000000), -(30893,0,0x0000000008000000), -(31216,1,0x0000000002000004), -(31217,1,0x0000000002000004), -(31218,1,0x0000000002000004), -(31219,1,0x0000000002000004), -(31220,1,0x0000000002000004), -(31226,0,0x000000000001E000), -(31227,0,0x000000000001E000), -(31234,0,0x000001002612030F), -(31234,1,0x0000000000100100), -(31235,0,0x000001002612030F), -(31235,1,0x0000000000100100), -(31236,0,0x000001002612030F), -(31236,1,0x0000000000100100), -(31237,0,0x000001002612030F), -(31237,1,0x0000000000100100), -(31238,0,0x000001002612030F), -(31238,1,0x0000000000100100), -(31571,0,0x0000000200000000), -(31572,0,0x0000000200000000), -(31573,0,0x0000000200000000), -(31579,0,0x0000000000200000), -(31579,1,0x0000000000000800), -(31582,0,0x0000000000200000), -(31582,1,0x0000000000000800), -(31583,0,0x0000000000200000), -(31583,1,0x0000000000000800), -(31656,0,0x0000000000000001), -(31657,0,0x0000000000000001), -(31658,0,0x0000000000000001), -(31659,0,0x0000000000000001), -(31660,0,0x0000000000000001), -(31670,0,0x0000000500000200), -(31672,0,0x0000000500000200), -(31682,0,0x0000000000000020), -(31682,1,0x0000000000000020), -(31683,0,0x0000000000000020), -(31683,1,0x0000000000000020), -(31684,0,0x0000000000000020), -(31684,1,0x0000000000000020), -(31685,0,0x0000000000000020), -(31685,1,0x0000000000000020), -(31686,0,0x0000000000000020), -(31686,1,0x0000000000000020), -(31821,0,0x0000000004020048), -(31825,0,0x0000000000001020), -(31825,1,0x0000000200000000), -(31826,0,0x0000000000001020), -(31826,1,0x0000000200000000), -(31834,0,0x0000000080000000), -(31844,1,0x000005401A00038C), -(31845,1,0x000005401A00038C), -(31848,0,0x0000000000400000), -(31848,1,0x0000000000400000), -(31849,0,0x0000000000400000), -(31849,1,0x0000000000400000), -(31869,0,0x0000002000000000), -(31870,0,0x0000002000000000), -(31879,0,0x0000000800000400), -(31880,0,0x0000000800000400), -(31881,0,0x0000000800000400), -(31882,0,0x0000000800000400), -(31883,0,0x0000000800000400), -(32043,1,0x000004000A000000), -(32203,1,0x0001100001C22000), -(32381,0,0x0000000000000002), -(32382,0,0x0000000000000002), -(32383,0,0x0000000000000002), -(32412,0,0x0000000000000400), -(32477,0,0x0000020000000000), -(32483,0,0x0000020000000000), -(32484,0,0x0000020000000000), -(32601,1,0x0000000020800008), -(32743,0,0x0000000000000800), -(32973,0,0x0000000090100000), -(33018,0,0x0000001000000000), -(33020,0,0x0000000000000400), -(33063,0,0x0000040000000000), -(33066,0,0x0000000000000002), -(33151,0,0x0000000000000080), -(33151,1,0x0000000000000080), -(33151,2,0x0000000000000080), -(33158,0,0x0000000000001000), -(33158,1,0x0000000000000800), -(33159,0,0x0000000000001000), -(33159,1,0x0000000000000800), -(33160,0,0x0000000000001000), -(33160,1,0x0000000000000800), -(33161,0,0x0000000000001000), -(33161,1,0x0000000000000800), -(33162,0,0x0000000000001000), -(33162,1,0x0000000000000800), -(33167,0,0x0000008100000000), -(33171,0,0x0000008100000000), -(33172,0,0x0000008100000000), -(33174,0,0x0000000000000020), -(33174,1,0x0000000000000020), -(33182,0,0x0000000000000020), -(33182,1,0x0000000000000020), -(33186,0,0x0000008000000000), -(33186,1,0x0000008000002080), -(33190,0,0x0000008000000000), -(33190,1,0x0000008000002080), -(33213,0,0x0000000000822000), -(33214,0,0x0000000000822000), -(33215,0,0x0000000000822000), -(33221,0,0x0000000200002000), -(33222,0,0x0000000200002000), -(33223,0,0x0000000200002000), -(33224,0,0x0000000200002000), -(33225,0,0x0000000200002000), -(33333,0,0x0000000020000000), -(33421,0,0x0000000200000000), -(33557,0,0x0000000000000200), -(33557,1,0x0000000020000000), -(33565,0,0x0000000000001000), -(33600,0,0x0000000000000400), -(33600,1,0x0000000000000400), -(33601,0,0x0000000000000400), -(33601,1,0x0000000000000400), -(33602,0,0x0000000000000400), -(33602,1,0x0000000000000400), -(33603,0,0x0000000000000004), -(33603,1,0x0000000000000001), -(33604,0,0x0000000000000004), -(33604,1,0x0000000000000001), -(33605,0,0x0000000000000004), -(33605,1,0x0000000000000001), -(33606,0,0x0000000000000004), -(33606,1,0x0000000000000001), -(33607,0,0x0000000000000004), -(33607,1,0x0000000000000001), -(33693,0,0x0000000000008000), -(33696,0,0x0000000000000001), -(33713,0,0x0000000200000000), -(33714,0,0x0000000200000000), -(33830,0,0x0000002000000000), -(33830,1,0x0000002000000000), -(33877,0,0x0000000000000002), -(33879,0,0x0000000000000020), -(33880,0,0x0000000000000020), -(33886,0,0x00000010000000D0), -(33887,0,0x00000010000000D0), -(33888,0,0x00000010000000D0), -(33889,0,0x00000010000000D0), -(33890,0,0x00000010000000D0), -(34128,0,0x0000001000000000), -(34129,0,0x0000000040000000), -(34129,1,0x0000000040000000), -(34131,0,0x0000000000000080), -(34131,1,0x0000000000000080), -(34253,0,0x0000010000000000), -(34297,0,0x0000080000000000), -(34300,0,0x0000080000000000), -(34318,0,0x0000000000000400), -(34318,1,0x0000002000000000), -(34323,0,0x0000008000800000), -(34453,1,0x0000000400000000), -(34454,1,0x0000000400000000), -(34455,0,0x0000002000000000), -(34455,1,0x0000004000000000), -(34459,0,0x0000002000000000), -(34459,1,0x0000004000000000), -(34460,0,0x0000002000000000), -(34460,1,0x0000004000000000), -(34462,1,0x0000000800000000), -(34464,1,0x0000000800000000), -(34465,1,0x0000000800000000), -(34466,1,0x0000001000000000), -(34467,1,0x0000001000000000), -(34468,1,0x0000001000000000), -(34469,1,0x0000001000000000), -(34470,1,0x0000001000000000), -(34491,0,0x00004000000000C2), -(34491,1,0x0000000000000080), -(34492,0,0x00004000000000C2), -(34492,1,0x0000000000000080), -(34493,0,0x00004000000000C2), -(34493,1,0x0000000000000080), -(34520,1,0x0000000000000000), -(34754,0,0x0000000400001800), -(34936,0,0x0000004000000001), -(34948,1,0x0000000000000020), -(34949,1,0x0000000000000020), -(35029,1,0x0000080000000000), -(35030,1,0x0000080000000000), -(35098,0,0x0000000000020801), -(35099,0,0x0000000000020801), -(35104,0,0x0000000000001000), -(35104,1,0x0000000000002000), -(35110,0,0x0000000000001000), -(35110,1,0x0000000000002000), -(35111,0,0x0000000000001000), -(35111,1,0x0000000000002000), -(35363,0,0x0000000000000005), -(35364,0,0x0000000000000005), -(35396,1,0x000004000A000000), -(35397,1,0x000004000A000000), -(35446,0,0x0000000002000000), -(35446,1,0x0000000002000000), -(35448,0,0x0000000002000000), -(35448,1,0x0000000002000000), -(35449,0,0x0000000002000000), -(35449,1,0x0000000002000000), -(35450,0,0x0000000002000000), -(35450,1,0x0000000002000000), -(35451,0,0x0000000002000000), -(35451,1,0x0000000002000000), -(35578,0,0x0000000028E212F7), -(35581,0,0x0000000028E212F7), -(36032,0,0x0000000020000000), -(36032,1,0x0000000020000000), -(36413,0,0x0000000000000001), -(36563,1,0x0000000000000204), -(36563,2,0x0000000000000100), -(37166,0,0x0000000000800000), -(37167,0,0x0000000000040000), -(37171,0,0x00000009003E0000), -(37180,0,0x0000000000000020), -(37181,0,0x0000000400000000), -(37183,0,0x0000010000000000), -(37184,0,0x0000040008000000), -(37184,1,0x0000040008000000), -(37185,0,0x0000004000000000), -(37186,0,0x0000000020000000), -(37187,0,0x0000020000000000), -(37190,0,0x0000000000000008), -(37191,0,0x0000004000000000), -(37194,0,0x0000000000800000), -(37207,0,0x0000000000000002), -(37209,0,0x0000000000000400), -(37209,1,0x0000002000000000), -(37210,0,0x0000000000004000), -(37211,0,0x0000008000000000), -(37212,0,0x0000010000000000), -(37223,0,0x0000000000010000), -(37224,0,0x0000001000000000), -(37225,0,0x0000000000000080), -(37234,0,0x0000000000000080), -(37240,0,0x0000000000000080), -(37241,0,0x0000020000000000), -(37286,0,0x0000000000000010), -(37287,0,0x0000E000E2000000), -(37292,0,0x0008000000000000), -(37297,0,0x0000100000000000), -(37313,0,0x0000000000000040), -(37314,0,0x0000001000000000), -(37316,0,0x0000000000000040), -(37325,0,0x0000000000000040), -(37333,0,0x0000000000008000), -(37333,1,0x0000010000000000), -(37376,0,0x0000001000000000), -(37380,0,0x0000000000000006), -(37423,0,0x0000000000000004), -(37424,0,0x0000000000008000), -(37438,0,0x0000000000000021), -(37439,0,0x0000002000000000), -(37439,1,0x0000004000000000), -(37439,2,0x0000008000000000), -(37441,0,0x0000000020000000), -(37441,1,0x0000000020000000), -(37447,0,0x0000010000000000), -(37481,0,0x0000000000000080), -(37484,0,0x0000000000000100), -(37485,0,0x0000000000001000), -(37505,0,0x0000000100000000), -(37507,0,0x0000000000000800), -(37508,0,0x0000000100061800), -(37508,1,0x0000000000000000), -(37512,0,0x00000080000F0000), -(37513,0,0x0000000000000001), -(37517,0,0x0000014D2A600CEF), -(37518,0,0x0000000400000000), -(37522,0,0x0000000000001000), -(37535,0,0x0000000002000000), -(37536,0,0x0000000000010000), -(37556,0,0x0000000400000000), -(37564,0,0x0000000000000200), -(37565,0,0x0000000000001000), -(37570,1,0x0000010000000000), -(37571,0,0x0000000000000080), -(37571,1,0x0000000000800000), -(37593,0,0x0000000000000040), -(37706,0,0x0000000411041E40), -(37721,0,0x00000010000000F0), -(37722,0,0x00000000000001C0), -(37723,0,0x00000000C0000000), -(37736,0,0x0000040000000000), -(37736,1,0x0000004000000000), -(37737,0,0x0000000000000040), -(37738,0,0x0000000000000040), -(37739,0,0x0000000080000000), -(37740,0,0x0000000000000001), -(37742,0,0x0000004000000000), -(37760,0,0x0000000000000001), -(37762,0,0x0000001000000000), -(37763,0,0x0000800000000000), -(37878,0,0x00000010000000F0), -(37879,0,0x00000000C0000000), -(37880,0,0x0000000411041E40), -(37881,0,0x00000000000001C0), -(38314,0,0x0000E000E2000000), -(38321,0,0x0000000000000020), -(38322,0,0x0000000000000100), -(38388,0,0x0000000000040000), -(38389,0,0x0000000E00000006), -(38392,0,0x0000000100000000), -(38393,0,0x0000000000000001), -(38396,0,0x0000000004000000), -(38397,0,0x0000000000000821), -(38398,0,0x0000000020000000), -(38399,0,0x0000000002000000), -(38407,0,0x0000000100000000), -(38408,0,0x0000008000000000), -(38410,0,0x0000000000000200), -(38411,0,0x0000000000001000), -(38412,0,0x0000000000002000), -(38413,0,0x0000000000008000), -(38414,0,0x0000000000000002), -(38415,0,0x0000000000000004), -(38416,0,0x0010000000800000), -(38416,1,0x0010000000800000), -(38417,0,0x0000000200000000), -(38420,0,0x0000000000000020), -(38421,0,0x0000100000000000), -(38422,0,0x0000000000000020), -(38424,0,0x0000008000000000), -(38425,0,0x0000000040000000), -(38426,0,0x0000000080000000), -(38429,0,0x0000000090100000), -(38434,0,0x0000000000000100), -(38435,0,0x0000000000000080), -(38436,0,0x0000000000000001), -(38447,0,0x0000040000000000), -(38447,1,0x0000004000000000), -(38466,0,0x0008000000000000), -(38499,0,0x0000008000000000), -(38501,0,0x0000000000000080), -(38522,0,0x0000000040000000), -(39805,0,0x0000000000000003), -(39805,1,0x0000000000000003), -(39926,1,0x0000080000000000), -(39926,2,0x0000200000000000), -(39950,0,0x0000000000000040), -(40389,0,0x0000800000000000), -(40460,0,0x00000009003E0000), -(41021,0,0x0000004000000000), -(41021,1,0x0000004000000000), -(41026,0,0x0000004000000000), -(41026,1,0x0000004000000000), -(41037,0,0x0000044000000000), -(41042,0,0x0000000000800000), -(42367,0,0x0000001000000000), -(43339,0,0x0000000090100000), -(43725,0,0x0000001000000000), -(43736,0,0x0000000000000010), -(43743,1,0x0000000008000400), -(43752,0,0x0000000000000100), -(43837,0,0x0000000080000000), -(43840,0,0x0000044000000000), -(43841,0,0x0000000000000002), -(43842,0,0x0000044000000000), -(43843,0,0x0000044000000000), -(43844,0,0x0000000000000002), -(43845,0,0x0000000000000002), -(43850,0,0x0000000000800000), -(43851,0,0x0000000000800000), -(43852,0,0x0000000000800000), -(43854,0,0x0000004000000000), -(43855,0,0x0000004000000000), -(43856,0,0x0000004000000000), -(43857,0,0x0000001000000000), -(43858,0,0x0000001000000000), -(43859,0,0x0000001000000000), -(43860,0,0x0000000090100000), -(43861,0,0x0000000090100000), -(43862,0,0x0000000090100000), -(44292,0,0x0000000000001000), -(44293,0,0x0000000000000200), -(44295,0,0x0000000090100000), -(44296,0,0x0000000000000001), -(44297,0,0x0000000000010000), -(44299,0,0x0000000000040000), -(44300,0,0x0000800000000000), -(44301,0,0x0000000001000000), -(44302,0,0x0000000001000000), -(44373,0,0x0000000000000000), -(46088,0,0x0000044000000000), -(46090,0,0x0000000000000002), -(46091,0,0x0000000000800000), -(46095,0,0x0000004000000000), -(46096,0,0x0000001000000000), -(46097,0,0x0000000090100000), -(46100,0,0x0000001000000000), -(46833,0,0x0000000000000004), -(46834,0,0x0000000000000040), -(46851,0,0x0001000000000000); - /*!40000 ALTER TABLE `spell_affect` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/wotlk_updates/6_character_achievement.sql b/sql/wotlk_updates/6_character_achievement.sql index fed3a6c39..23326eb6f 100644 --- a/sql/wotlk_updates/6_character_achievement.sql +++ b/sql/wotlk_updates/6_character_achievement.sql @@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS `character_achievement` ( `achievement` int(11) NOT NULL, `date` int(11) NOT NULL, PRIMARY KEY (`guid`,`achievement`) - ) ENGINE=MyISAM DEFAULT CHARSET=latin1; + ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `character_achievement_progress` ( `guid` int(11) NOT NULL, @@ -11,4 +11,4 @@ CREATE TABLE IF NOT EXISTS `character_achievement_progress` ( `counter` int(11) NOT NULL, `date` int(11) NOT NULL, PRIMARY KEY (`guid`,`criteria`) - ) ENGINE=MyISAM DEFAULT CHARSET=latin1; + ) ENGINE=MyISAM DEFAULT CHARSET=utf8; From c51a6bc59e823c5d5476e5a4994980c1c34c7cf9 Mon Sep 17 00:00:00 2001 From: ApoC Date: Mon, 15 Dec 2008 14:31:31 +0100 Subject: [PATCH 189/256] Fixed runtime abort in WorldSession::HandleChangePlayerNameOpcodeCallBack . Signed-off-by: ApoC --- src/game/CharacterHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 50c6df71f..cc93b4369 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -978,7 +978,7 @@ 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(),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; From a5331ab517202d1bab1417e02fc171ba2b3d1dab Mon Sep 17 00:00:00 2001 From: ApoC Date: Mon, 15 Dec 2008 23:52:46 +0100 Subject: [PATCH 190/256] [6910] Implemented rewritten arenas. Original author w12x@getmangos.com Many thanks also to: Balrok@github.com for long time updating. Triply@github.com for great work in rewriting process. All who I forget to name. Signed-off-by: ApoC --- .../2008_12_15_01_character_arenas.sql | 6 + sql/updates/2008_12_15_01_mangos_arenas.sql | 26 + src/game/ArenaTeam.cpp | 355 ++-- src/game/ArenaTeam.h | 91 +- src/game/ArenaTeamHandler.cpp | 75 +- src/game/BattleGround.cpp | 527 ++++-- src/game/BattleGround.h | 58 +- src/game/BattleGroundAB.cpp | 8 + src/game/BattleGroundBE.cpp | 55 +- src/game/BattleGroundBE.h | 5 +- src/game/BattleGroundEY.cpp | 23 +- src/game/BattleGroundHandler.cpp | 605 ++++--- src/game/BattleGroundMgr.cpp | 1430 ++++++++++++++--- src/game/BattleGroundMgr.h | 141 +- src/game/BattleGroundNA.cpp | 69 +- src/game/BattleGroundNA.h | 13 +- src/game/BattleGroundRL.cpp | 66 +- src/game/BattleGroundRL.h | 13 +- src/game/BattleGroundWS.cpp | 37 +- src/game/CharacterHandler.cpp | 6 +- src/game/Chat.cpp | 2 + src/game/Chat.h | 2 + src/game/GameEvent.cpp | 2 +- src/game/Group.cpp | 48 + src/game/Group.h | 1 + src/game/Language.h | 25 +- src/game/Level1.cpp | 31 +- src/game/Level3.cpp | 7 + src/game/MapInstanced.cpp | 12 +- src/game/MapManager.cpp | 2 +- src/game/MovementHandler.cpp | 45 +- src/game/ObjectMgr.cpp | 40 +- src/game/ObjectMgr.h | 18 +- src/game/PetitionsHandler.cpp | 147 +- src/game/Player.cpp | 123 +- src/game/Player.h | 68 +- src/game/SpellAuras.cpp | 3 +- src/game/SpellEffects.cpp | 2 +- src/game/Unit.cpp | 48 +- src/game/Unit.h | 1 + src/game/World.cpp | 29 +- src/game/World.h | 6 + src/game/WorldSession.h | 3 +- src/game/debugcmds.cpp | 7 + src/mangosd/mangosd.conf.dist.in | 42 + src/shared/Database/DBCStructure.h | 5 +- src/shared/revision_nr.h | 2 +- 47 files changed, 3406 insertions(+), 924 deletions(-) create mode 100644 sql/updates/2008_12_15_01_character_arenas.sql create mode 100644 sql/updates/2008_12_15_01_mangos_arenas.sql diff --git a/sql/updates/2008_12_15_01_character_arenas.sql b/sql/updates/2008_12_15_01_character_arenas.sql new file mode 100644 index 000000000..2976d343e --- /dev/null +++ b/sql/updates/2008_12_15_01_character_arenas.sql @@ -0,0 +1,6 @@ +CREATE TABLE `saved_variables` ( + `NextArenaPointDistributionTime` bigint(40) UNSIGNED NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Variable Saves'; + +ALTER TABLE `arena_team_member` ADD COLUMN `personal_rating` int(10) UNSIGNED NOT NULL DEFAULT '0'; +ALTER TABLE `characters` ADD COLUMN `arena_pending_points` int(10) UNSIGNED NOT NULL default '0'; diff --git a/sql/updates/2008_12_15_01_mangos_arenas.sql b/sql/updates/2008_12_15_01_mangos_arenas.sql new file mode 100644 index 000000000..f57ea8a3f --- /dev/null +++ b/sql/updates/2008_12_15_01_mangos_arenas.sql @@ -0,0 +1,26 @@ +DELETE FROM `command` WHERE `name` = "flusharenapoints"; +INSERT INTO `command` (`name`, `security`, `help`) VALUES +('flusharenapoints','3','Syntax: .flusharenapoints\r\n\r\nUse it to distribute arena points based on arena team ratings, and start a new week.'); + +DELETE FROM mangos_string WHERE entry BETWEEN 7007 AND 7023; + +INSERT INTO mangos_string (entry, content_default) VALUES + (7007,'Your group is too large for this battleground. Please regroup to join.'), + (7008,'Your group is too large for this arena. Please regroup to join.'), + (7009,'Your group has members not in your arena team. Please regroup to join.'), + (7010,'Your group does not have enough players to join this match.'), + (7011,'The Gold Team wins!'), + (7012,'The Green Team wins!'), + (7013, 'There aren\'t enough players in this battleground. It will end soon unless some more players join to balance the fight.'), + (7014, 'Your group has an offline member. Please remove him before joining.'), + (7015, 'Your group has players from the opposing faction. You can\'t join the battleground as a group.'), + (7016, 'Your group has players from different battleground brakets. You can\'t join as group.'), + (7017, 'Someone in your party is already in this battleground queue. (S)he must leave it before joining as group.'), + (7018, 'Someone in your party is Deserter. You can\'t join as group.'), + (7019, 'Someone in your party is already in three battleground queues. You cannot join as group.'), + (7020, 'You cannot teleport to a battleground or arena map.'), + (7021, 'You cannot summon players to a battleground or arena map.'), + (7022, 'You must be in GM mode to teleport to a player in a battleground.'), + (7023, 'You cannot teleport to a battleground from another battleground. Please leave the current battleground first.'); + +DELETE FROM mangos_string WHERE entry = 714 OR entry = 716; diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp index 72ed8d679..b6df34f98 100644 --- a/src/game/ArenaTeam.cpp +++ b/src/game/ArenaTeam.cpp @@ -44,7 +44,7 @@ ArenaTeam::~ArenaTeam() } -bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamName) +bool ArenaTeam::Create(uint64 captainGuid, uint32 type, std::string ArenaTeamName) { if(!objmgr.GetPlayer(captainGuid)) // player not exist return false; @@ -67,9 +67,9 @@ bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid='%u'", Id); CharacterDatabase.PExecute("INSERT INTO arena_team (arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor) " "VALUES('%u','%s','%u','%u','%u','%u','%u','%u','%u')", - Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor); + Id, ArenaTeamName.c_str(), GUID_LOPART(CaptainGuid), Type, BackgroundColor, EmblemStyle, EmblemColor, BorderStyle, BorderColor); CharacterDatabase.PExecute("INSERT INTO arena_team_stats (arenateamid, rating, games, wins, played, wins2, rank) VALUES " - "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id,stats.rating,stats.games_week,stats.wins_week,stats.games_season,stats.wins_season,stats.rank); + "('%u', '%u', '%u', '%u', '%u', '%u', '%u')", Id, stats.rating, stats.games_week, stats.wins_week, stats.games_season, stats.wins_season, stats.rank); CharacterDatabase.CommitTransaction(); @@ -77,7 +77,7 @@ bool ArenaTeam::create(uint64 captainGuid, uint32 type, std::string ArenaTeamNam return true; } -bool ArenaTeam::AddMember(uint64 PlayerGuid) +bool ArenaTeam::AddMember(const uint64& PlayerGuid) { std::string plName; uint8 plClass; @@ -132,39 +132,23 @@ bool ArenaTeam::AddMember(uint64 PlayerGuid) newmember.personal_rating = 1500; members.push_back(newmember); - CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid,guid) VALUES ('%u', '%u')", Id, GUID_LOPART(newmember.guid)); + CharacterDatabase.PExecute("INSERT INTO arena_team_member (arenateamid, guid, personal_rating) VALUES ('%u', '%u', '%u')", Id, GUID_LOPART(newmember.guid), newmember.personal_rating ); if(pl) { pl->SetInArenaTeam(Id, GetSlot()); pl->SetArenaTeamIdInvited(0); + pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot()*6) + 5, newmember.personal_rating ); // hide promote/remove buttons if(CaptainGuid != PlayerGuid) - pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); - } - else - { - Tokens tokens; - if(Player::LoadValuesArrayFromDB(tokens,PlayerGuid)) - { - Player::SetUInt32ValueInArray(tokens,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), Id); - // hide promote/remove buttons - if(CaptainGuid != PlayerGuid) - Player::SetUInt32ValueInArray(tokens,PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); - - Player::SaveValuesArrayInDB(tokens,PlayerGuid); - } + pl->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + 1, 1); } return true; } bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId) { - LoadStatsFromDB(ArenaTeamId); - LoadMembersFromDB(ArenaTeamId); - - // 0 1 2 3 4 5 6 7 8 QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid,name,captainguid,type,BackgroundColor,EmblemStyle,EmblemColor,BorderStyle,BorderColor FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); if(!result) @@ -184,6 +168,22 @@ bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId) delete result; + // only load here, so additional checks can be made + LoadStatsFromDB(ArenaTeamId); + LoadMembersFromDB(ArenaTeamId); + + if(Empty()) + { + // arena team is empty, delete from db + CharacterDatabase.BeginTransaction(); + CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", ArenaTeamId); + CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); + CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId); + CharacterDatabase.CommitTransaction(); + // return false + return false; + } + return true; } @@ -209,49 +209,37 @@ void ArenaTeam::LoadStatsFromDB(uint32 ArenaTeamId) void ArenaTeam::LoadMembersFromDB(uint32 ArenaTeamId) { - Field *fields; - - QueryResult *result = CharacterDatabase.PQuery("SELECT guid,played_week,wons_week,played_season,wons_season FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); + // 0 1 2 3 4 5 6 7 + QueryResult *result = CharacterDatabase.PQuery("SELECT member.guid,played_week,wons_week,played_season,wons_season,personal_rating,name,class " + "FROM arena_team_member member " + "INNER JOIN characters chars on member.guid = chars.guid " + "WHERE member.arenateamid = '%u'", ArenaTeamId); if(!result) return; do { - fields = result->Fetch(); + Field *fields = result->Fetch(); ArenaTeamMember newmember; newmember.guid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - LoadPlayerStats(&newmember); newmember.games_week = fields[1].GetUInt32(); newmember.wins_week = fields[2].GetUInt32(); newmember.games_season = fields[3].GetUInt32(); newmember.wins_season = fields[4].GetUInt32(); + newmember.personal_rating = fields[5].GetUInt32(); + newmember.name = fields[6].GetCppString(); + newmember.Class = fields[7].GetUInt8(); members.push_back(newmember); }while( result->NextRow() ); delete result; } -void ArenaTeam::LoadPlayerStats(ArenaTeamMember *member) -{ - Field *fields; - - QueryResult *result = CharacterDatabase.PQuery("SELECT name,class FROM characters WHERE guid = '%u'", GUID_LOPART(member->guid)); - if(!result) - return; - fields = result->Fetch(); - member->name = fields[0].GetCppString(); - member->Class = fields[1].GetUInt8(); - - delete result; -} - -void ArenaTeam::SetCaptain(uint64 guid) +void ArenaTeam::SetCaptain(const uint64& guid) { // disable remove/promote buttons Player *oldcaptain = objmgr.GetPlayer(GetCaptain()); if(oldcaptain) oldcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1); - else - Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 1, GetCaptain()); // set new captain CaptainGuid = guid; @@ -263,14 +251,11 @@ void ArenaTeam::SetCaptain(uint64 guid) Player *newcaptain = objmgr.GetPlayer(guid); if(newcaptain) newcaptain->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0); - else - Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 1 + (GetSlot() * 6), 0, guid); } void ArenaTeam::DelMember(uint64 guid) { - MemberList::iterator itr; - for (itr = members.begin(); itr != members.end(); itr++) + for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) { if (itr->guid == guid) { @@ -280,17 +265,19 @@ void ArenaTeam::DelMember(uint64 guid) } Player *player = objmgr.GetPlayer(guid); + if(player) { player->SetInArenaTeam(0, GetSlot()); player->GetSession()->SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, GetName(), "", 0); - } - else - { - Player::SetUInt32ValueInDB(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6), 0, guid); + // delete all info regarding this team + for(int i = 0; i < 6; ++i) + { + player->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (GetSlot() * 6) + i, 0); + } } - CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE guid = '%u'", GUID_LOPART(guid)); + CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u' AND guid = '%u'", GetId(), GUID_LOPART(guid)); } void ArenaTeam::Disband(WorldSession *session) @@ -300,23 +287,15 @@ void ArenaTeam::Disband(WorldSession *session) session->BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_DISBANDED_S, 2, session->GetPlayerName(), GetName(), ""); BroadcastPacket(&data); - uint32 count = members.size(); - uint64 *memberGuids = new uint64[count]; - - MemberList::iterator itr; - uint32 i=0; - for(itr = members.begin(); itr != members.end(); itr++) + while (!members.empty()) { - memberGuids[i] = itr->guid; - ++i; + // Removing from members is done in DelMember. + DelMember(members.front().guid); } - for(uint32 j = 0; j < count; j++) - DelMember(memberGuids[j]); - delete[] memberGuids; - CharacterDatabase.BeginTransaction(); CharacterDatabase.PExecute("DELETE FROM arena_team WHERE arenateamid = '%u'", Id); + CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", Id); //< this should be alredy done by calling DelMember(memberGuids[j]); for each member CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", Id); CharacterDatabase.CommitTransaction(); objmgr.RemoveArenaTeam(this); @@ -334,34 +313,18 @@ void ArenaTeam::Roster(WorldSession *session) for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) { pl = objmgr.GetPlayer(itr->guid); - if(pl) - { - data << uint64(pl->GetGUID()); // guid - data << uint8(1); // online flag - data << pl->GetName(); // member name - data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown - data << uint8(pl->getLevel()); // unknown, probably level - data << uint8(pl->getClass()); // 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 - } - else - { - data << uint64(itr->guid); // guid - data << uint8(0); // online flag - data << itr->name; // member name - data << uint32(itr->guid == GetCaptain() ? 0 : 1);// unknown - data << uint8(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 << 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 } session->SendPacket(&data); sLog.outDebug("WORLD: Sent SMSG_ARENA_TEAM_ROSTER"); @@ -395,6 +358,18 @@ void ArenaTeam::Stats(WorldSession *session) session->SendPacket(&data); } +void ArenaTeam::NotifyStatsChanged() +{ + // this is called after a rated match ended + // updates arena team stats for every member of the team (not only the ones who participated!) + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + Player * plr = objmgr.GetPlayer(itr->guid); + if(plr) + Stats(plr->GetSession()); + } +} + void ArenaTeam::InspectStats(WorldSession *session, uint64 guid) { ArenaTeamMember* member = GetMember(guid); @@ -408,8 +383,8 @@ void ArenaTeam::InspectStats(WorldSession *session, uint64 guid) data << uint32(stats.rating); // rating data << uint32(stats.games_season); // season played data << uint32(stats.wins_season); // season wins - data << member->games_season; // played (count of all games, that the inspected member participated...) - data << member->personal_rating; // personal rating + data << uint32(member->games_season); // played (count of all games, that the inspected member participated...) + data << uint32(member->personal_rating); // personal rating session->SendPacket(&data); } @@ -458,18 +433,6 @@ void ArenaTeam::SetStats(uint32 stat_type, uint32 value) } } -uint8 ArenaTeam::GetSlot() const -{ - uint8 slot = GetSlotByType(GetType()); - if(slot >= MAX_ARENA_SLOT) - { - sLog.outError("Unknown arena team type %u for arena team %u", uint32(GetType()), GetId()); - return 0; // better return existed slot to prevent untelated data curruption - } - - return slot; -} - void ArenaTeam::BroadcastPacket(WorldPacket *packet) { for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) @@ -490,18 +453,184 @@ uint8 ArenaTeam::GetSlotByType( uint32 type ) default: break; } + sLog.outError("FATAL: Unknown arena team type %u for some arena team", type); return 0xFF; } -bool ArenaTeam::HaveMember( uint64 guid ) const +bool ArenaTeam::HaveMember( const uint64& guid ) const { for (MemberList::const_iterator itr = members.begin(); itr != members.end(); ++itr) - if(itr->guid==guid) + if(itr->guid == guid) return true; return false; } +uint32 ArenaTeam::GetPoints(uint32 MemberRating) +{ + // returns how many points would be awarded with this team type with this rating + float points; + + uint32 rating = MemberRating + 150 < stats.rating ? MemberRating : stats.rating; + + if(rating<=1500) + points = (float)rating * 0.22f + 14.0f; + else + points = 1511.26f / (1.0f + 1639.28f * exp(-0.00412f * (float)rating)); + + // type penalties for <5v5 teams + if(Type == ARENA_TEAM_2v2) + points *= 0.76f; + else if(Type == ARENA_TEAM_3v3) + points *= 0.88f; + + return (uint32) points; +} + +float ArenaTeam::GetChanceAgainst(uint32 own_rating, uint32 enemy_rating) +{ + // returns the chance to win against a team with the given rating, used in the rating adjustment calculation + // ELO system + return 1.0f/(1.0f+exp(log(10.0f)*(float)((float)enemy_rating - (float)own_rating)/400.0f)); +} + +int32 ArenaTeam::WonAgainst(uint32 againstRating) +{ + // called when the team has won + //'chance' calculation - to beat the opponent + float chance = GetChanceAgainst(stats.rating,againstRating); + // calculate the rating modification (ELO system with k=32) + int32 mod = (int32)floor(32.0f * (1.0f - chance)); + // modify the team stats accordingly + stats.rating += mod; + stats.games_week += 1; + stats.wins_week += 1; + stats.games_season += 1; + stats.wins_season += 1; + //update team's rank + stats.rank = 1; + ObjectMgr::ArenaTeamMap::iterator i = objmgr.GetArenaTeamMapBegin(); + for ( ; i != objmgr.GetArenaTeamMapEnd(); ++i) + { + if (i->second->GetType() == this->Type && i->second->GetStats().rating > stats.rating) + ++stats.rank; + } + + // return the rating change, used to display it on the results screen + return mod; +} + +int32 ArenaTeam::LostAgainst(uint32 againstRating) +{ + // called when the team has lost + //'chance' calculation - to loose to the opponent + float chance = GetChanceAgainst(stats.rating,againstRating); + // calculate the rating modification (ELO system with k=32) + int32 mod = (int32)ceil(32.0f * (0.0f - chance)); + // modify the team stats accordingly + stats.rating += mod; + stats.games_week += 1; + stats.games_season += 1; + //update team's rank + + stats.rank = 1; + ObjectMgr::ArenaTeamMap::iterator i = objmgr.GetArenaTeamMapBegin(); + for ( ; i != objmgr.GetArenaTeamMapEnd(); ++i) + { + if (i->second->GetType() == this->Type && i->second->GetStats().rating > stats.rating) + ++stats.rank; + } + + // return the rating change, used to display it on the results screen + return mod; +} + +void ArenaTeam::MemberLost(Player * plr, uint32 againstRating) +{ + // called for each participant of a match after losing + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + if(itr->guid == plr->GetGUID()) + { + // update personal rating + float chance = GetChanceAgainst(itr->personal_rating, againstRating); + int32 mod = (int32)ceil(32.0f * (0.0f - chance)); + itr->ModifyPersonalRating(plr, mod, GetSlot()); + // update personal played stats + itr->games_week +=1; + itr->games_season +=1; + // update the unit fields + plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->games_week); + plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->games_season); + return; + } + } +} + +void ArenaTeam::MemberWon(Player * plr, uint32 againstRating) +{ + // called for each participant after winning a match + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + if(itr->guid == plr->GetGUID()) + { + // update personal rating + float chance = GetChanceAgainst(itr->personal_rating, againstRating); + int32 mod = (int32)floor(32.0f * (1.0f - chance)); + itr->ModifyPersonalRating(plr, mod, GetSlot()); + // update personal stats + itr->games_week +=1; + itr->games_season +=1; + itr->wins_season += 1; + itr->wins_week += 1; + // update unit fields + plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 2, itr->games_week); + plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + 6 * GetSlot() + 3, itr->games_season); + return; + } + } +} + +void ArenaTeam::UpdateArenaPointsHelper(std::map& PlayerPoints) +{ + // called after a match has ended and the stats are already modified + // helper function for arena point distribution (this way, when distributing, no actual calculation is required, just a few comparisons) + // 10 played games per week is a minimum + if (stats.games_week < 10) + return; + // to get points, a player has to participate in at least 30% of the matches + uint32 min_plays = (uint32) ceil(stats.games_week * 0.3); + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + // the player participated in enough games, update his points + uint32 points_to_add = 0; + if (itr->games_week >= min_plays) + points_to_add = GetPoints(itr->personal_rating); + // OBSOLETE : CharacterDatabase.PExecute("UPDATE arena_team_member SET points_to_add = '%u' WHERE arenateamid = '%u' AND guid = '%u'", points_to_add, Id, itr->guid); + + std::map::iterator plr_itr = PlayerPoints.find(GUID_LOPART(itr->guid)); + if (plr_itr != PlayerPoints.end()) + { + //check if there is already more points + if (plr_itr->second < points_to_add) + PlayerPoints[GUID_LOPART(itr->guid)] = points_to_add; + } + else + PlayerPoints[GUID_LOPART(itr->guid)] = points_to_add; + } +} + +void ArenaTeam::SaveToDB() +{ + // save team and member stats to db + // called after a match has ended, or when calculating arena_points + CharacterDatabase.PExecute("UPDATE arena_team_stats SET rating = '%u',games = '%u',played = '%u',rank = '%u',wins = '%u',wins2 = '%u' WHERE arenateamid = '%u'", stats.rating, stats.games_week, stats.games_season, stats.rank, stats.wins_week, stats.wins_season, GetId()); + for(MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) + { + CharacterDatabase.PExecute("UPDATE arena_team_member SET played_week = '%u', wons_week = '%u', played_season = '%u', wons_season = '%u', personal_rating = '%u' WHERE arenateamid = '%u' AND guid = '%u'", itr->games_week, itr->wins_week, itr->games_season, itr->wins_season, itr->personal_rating, Id, itr->guid); + } +} + void ArenaTeam::FinishWeek() { stats.games_week = 0; // played this week @@ -519,18 +648,18 @@ arenateam fields (id from 2.3.3 client): 1415 - 0=captain, 1=member 1416 - played this week 1417 - played this season -1418 - unk +1418 - unk - rank? 1419 - personal arena rating 1420 - arena team id 3v3 1421 - 0=captain, 1=member 1422 - played this week 1423 - played this season -1424 - unk +1424 - unk - rank? 1425 - personal arena rating 1426 - arena team id 5v5 1427 - 0=captain, 1=member 1428 - played this week 1429 - played this season -1430 - unk +1430 - unk - rank? 1431 - personal arena rating */ diff --git a/src/game/ArenaTeam.h b/src/game/ArenaTeam.h index 43adca888..ba19c53f9 100644 --- a/src/game/ArenaTeam.h +++ b/src/game/ArenaTeam.h @@ -43,7 +43,9 @@ enum ArenaTeamCommandErrors ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM = 0x09, ERR_ARENA_TEAM_PLAYER_NOT_IN_TEAM_SS = 0x0A, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S = 0x0B, - ERR_ARENA_TEAM_NOT_ALLIED = 0x0C + ERR_ARENA_TEAM_NOT_ALLIED = 0x0C, + ERR_ARENA_TEAM_PLAYER_TO_LOW = 0x15, + ERR_ARENA_TEAM_FULL = 0x16 }; enum ArenaTeamEvents @@ -85,14 +87,22 @@ struct ArenaTeamMember { uint64 guid; std::string name; - //uint32 unk2; - //uint8 unk1; uint8 Class; uint32 games_week; uint32 wins_week; uint32 games_season; uint32 wins_season; uint32 personal_rating; + + void ModifyPersonalRating(Player* plr, int32 mod, uint32 slot) + { + if (personal_rating + mod < 0) + personal_rating = 0; + else + personal_rating += mod; + if(plr) + plr->SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot*6) + 5, personal_rating); + } }; struct ArenaTeamStats @@ -113,58 +123,78 @@ class ArenaTeam ArenaTeam(); ~ArenaTeam(); - bool create(uint64 CaptainGuid, uint32 type, std::string ArenaTeamName); + bool Create(uint64 CaptainGuid, uint32 type, std::string ArenaTeamName); void Disband(WorldSession *session); typedef std::list MemberList; - uint32 GetId() const { return Id; } - uint32 GetType() const { return Type; } - uint8 GetSlot() const; + uint32 GetId() const { return Id; } + uint32 GetType() const { return Type; } + uint8 GetSlot() const { return GetSlotByType(GetType()); } static uint8 GetSlotByType(uint32 type); - const uint64& GetCaptain() const { return CaptainGuid; } - std::string GetName() const { return Name; } + const uint64& GetCaptain() const { return CaptainGuid; } + std::string GetName() const { return Name; } const ArenaTeamStats& GetStats() const { return stats; } void SetStats(uint32 stat_type, uint32 value); - uint32 GetRating() const { return stats.rating; } + uint32 GetRating() const { return stats.rating; } - uint32 GetEmblemStyle() const { return EmblemStyle; } - uint32 GetEmblemColor() const { return EmblemColor; } - uint32 GetBorderStyle() const { return BorderStyle; } - uint32 GetBorderColor() const { return BorderColor; } + uint32 GetEmblemStyle() const { return EmblemStyle; } + uint32 GetEmblemColor() const { return EmblemColor; } + uint32 GetBorderStyle() const { return BorderStyle; } + uint32 GetBorderColor() const { return BorderColor; } uint32 GetBackgroundColor() const { return BackgroundColor; } - void SetCaptain(uint64 guid); - bool AddMember(uint64 PlayerGuid); + void SetCaptain(const uint64& guid); + bool AddMember(const uint64& PlayerGuid); + + // Shouldn't be const uint64& ed, because than can reference guid from members on Disband + // and this method removes given record from list. So invalid reference can happen. void DelMember(uint64 guid); void SetEmblem(uint32 backgroundColor, uint32 emblemStyle, uint32 emblemColor, uint32 borderStyle, uint32 borderColor); - uint32 GetMembersSize() const { return members.size(); } - MemberList::iterator membersbegin(){ return members.begin(); } - MemberList::iterator membersEnd(){ return members.end(); } - bool HaveMember(uint64 guid) const; - ArenaTeamMember* GetMember(uint64 guid) + size_t GetMembersSize() const { return members.size(); } + bool Empty() const { return members.empty(); } + MemberList::iterator membersBegin() { return members.begin(); } + MemberList::iterator membersEnd() { return members.end(); } + bool HaveMember(const uint64& guid) const; + + ArenaTeamMember* GetMember(const uint64& guid) { for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) - if(itr->guid==guid) + if(itr->guid == guid) return &(*itr); return NULL; } - ArenaTeamMember* GetMember(std::string& name) + + ArenaTeamMember* GetMember(const std::string& name) { for (MemberList::iterator itr = members.begin(); itr != members.end(); ++itr) - if(itr->name==name) + if(itr->name == name) return &(*itr); 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 LoadArenaTeamFromDB(uint32 ArenaTeamId); void LoadMembersFromDB(uint32 ArenaTeamId); void LoadStatsFromDB(uint32 ArenaTeamId); - void LoadPlayerStats(ArenaTeamMember* member); + + void SaveToDB(); void BroadcastPacket(WorldPacket *packet); @@ -173,6 +203,17 @@ class ArenaTeam void Stats(WorldSession *session); void InspectStats(WorldSession *session, uint64 guid); + uint32 GetPoints(uint32 MemberRating); + float GetChanceAgainst(uint32 own_rating, uint32 enemy_rating); + int32 WonAgainst(uint32 againstRating); + void MemberWon(Player * plr, uint32 againstRating); + int32 LostAgainst(uint32 againstRating); + void MemberLost(Player * plr, uint32 againstRating); + + void UpdateArenaPointsHelper(std::map & PlayerPoints); + + void NotifyStatsChanged(); + void FinishWeek(); protected: diff --git a/src/game/ArenaTeamHandler.cpp b/src/game/ArenaTeamHandler.cpp index 16784bbcb..d0e095237 100644 --- a/src/game/ArenaTeamHandler.cpp +++ b/src/game/ArenaTeamHandler.cpp @@ -30,7 +30,6 @@ void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data) { sLog.outDebug("MSG_INSPECT_ARENA_TEAMS"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 8); @@ -54,7 +53,6 @@ void WorldSession::HandleInspectArenaStatsOpcode(WorldPacket & recv_data) void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data) { sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_QUERY" ); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4); @@ -72,7 +70,6 @@ void WorldSession::HandleArenaTeamQueryOpcode(WorldPacket & recv_data) void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data) { sLog.outDebug( "WORLD: Received CMSG_ARENA_TEAM_ROSTER" ); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4); @@ -89,7 +86,6 @@ void WorldSession::HandleArenaTeamRosterOpcode(WorldPacket & recv_data) void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data) { sLog.outDebug("CMSG_ARENA_TEAM_ADD_MEMBER"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4+1); @@ -110,15 +106,13 @@ void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data) if(!player) { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", Invitedname, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); return; } if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - //SendArenaTeamCommandResult(ARENA_TEAM_INVITE_SS,"",Invitedname,ARENA_TEAM_PLAYER_NOT_FOUND_S); - // can't find related opcode - SendNotification(LANG_HIS_ARENA_LEVEL_REQ_ERROR, player->GetName()); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW); return; } @@ -141,21 +135,19 @@ void WorldSession::HandleArenaTeamAddMemberOpcode(WorldPacket & recv_data) if(player->GetArenaTeamId(arenateam->GetSlot())) { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); return; } if(player->GetArenaTeamIdInvited()) { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, player->GetName(), "", ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); return; } if(arenateam->GetMembersSize() >= arenateam->GetType() * 2) { - // should send an "arena team is full" or the likes message, I just don't know the proper values so... ERR_INTERNAL -// SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_INTERNAL); - SendNotification(LANG_YOUR_ARENA_TEAM_FULL, player->GetName()); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,arenateam->GetName(),"",ERR_ARENA_TEAM_FULL); return; } @@ -177,23 +169,25 @@ void WorldSession::HandleArenaTeamInviteAcceptOpcode(WorldPacket & /*recv_data*/ ArenaTeam *at = objmgr.GetArenaTeamById(_player->GetArenaTeamIdInvited()); if(!at) + return; + + if(_player->GetArenaTeamIdFromDB(_player->GetGUIDLow(), at->GetType())) { - // arena team not exist + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ALREADY_IN_ARENA_TEAM); // already in arena team that size return; } - if(_player->GetArenaTeamId(at->GetSlot())) - { - // already in arena team that size - return; - } - - // not let enemies sign petition if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && _player->GetTeam() != objmgr.GetPlayerTeamByGUID(at->GetCaptain())) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ARENA_TEAM_NOT_ALLIED);// not let enemies sign petition return; + } if(!at->AddMember(_player->GetGUID())) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S,"","",ERR_ARENA_TEAM_INTERNAL);// arena team not found return; + } // event WorldPacket data; @@ -211,7 +205,6 @@ void WorldSession::HandleArenaTeamInviteDeclineOpcode(WorldPacket & /*recv_data* void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data) { sLog.outDebug("CMSG_ARENA_TEAM_LEAVE"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4); @@ -220,10 +213,7 @@ void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data) ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); if(!at) - { - // send command result return; - } if(_player->GetGUID() == at->GetCaptain() && at->GetMembersSize() > 1) { // check for correctness @@ -245,13 +235,13 @@ void WorldSession::HandleArenaTeamLeaveOpcode(WorldPacket & recv_data) BuildArenaTeamEventPacket(&data, ERR_ARENA_TEAM_LEAVE_SS, 2, _player->GetName(), at->GetName(), ""); at->BroadcastPacket(&data); - //SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0); + //send you are no longer member of team + SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, at->GetName(), "", 0); } void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data) { sLog.outDebug("CMSG_ARENA_TEAM_DISBAND"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4); @@ -260,16 +250,13 @@ void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data) ArenaTeam *at = objmgr.GetArenaTeamById(ArenaTeamId); if(!at) - { - // arena team not found return; - } if(at->GetCaptain() != _player->GetGUID()) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_PERMISSIONS); return; - } + + if (at->IsFighting()) + return; at->Disband(this); delete at; @@ -278,7 +265,6 @@ void WorldSession::HandleArenaTeamDisbandOpcode(WorldPacket & recv_data) void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data) { sLog.outDebug("CMSG_ARENA_TEAM_REMOVE_FROM_TEAM"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4+1); @@ -303,11 +289,14 @@ void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data) ArenaTeamMember* member = at->GetMember(name); if(!member) // member not found + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); return; + } if(at->GetCaptain() == member->guid) { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); + SendArenaTeamCommandResult(ERR_ARENA_TEAM_QUIT_S, "", "", ERR_ARENA_TEAM_LEADER_LEAVE_S); return; } @@ -322,7 +311,6 @@ void WorldSession::HandleArenaTeamRemoveFromTeamOpcode(WorldPacket & recv_data) void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data) { sLog.outDebug("CMSG_ARENA_TEAM_PROMOTE_TO_CAPTAIN"); - //recv_data.hexlike(); CHECK_PACKET_SIZE(recv_data, 4+1); @@ -347,7 +335,10 @@ void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data ArenaTeamMember* member = at->GetMember(name); if(!member) // member not found + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", name, ERR_ARENA_TEAM_PLAYER_NOT_FOUND_S); return; + } if(at->GetCaptain() == member->guid) // target player already captain return; @@ -360,13 +351,13 @@ void WorldSession::HandleArenaTeamPromoteToCaptainOpcode(WorldPacket & recv_data at->BroadcastPacket(&data); } -void WorldSession::SendArenaTeamCommandResult(uint32 unk1, const std::string& str1, const std::string& str2, uint32 unk3) +void WorldSession::SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id) { - WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+str1.length()+1+str2.length()+1+4); - data << unk1; - data << str1; - data << str2; - data << unk3; + WorldPacket data(SMSG_ARENA_TEAM_COMMAND_RESULT, 4+team.length()+1+player.length()+1+4); + data << team_action; + data << team; + data << player; + data << error_id; SendPacket(&data); } diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 1a3d70fb6..5c2ca717a 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -24,6 +24,7 @@ #include "Language.h" #include "Chat.h" #include "SpellAuras.h" +#include "ArenaTeam.h" #include "World.h" #include "Util.h" @@ -47,6 +48,8 @@ BattleGround::BattleGround() m_Name = ""; m_LevelMin = 0; m_LevelMax = 0; + m_InBGFreeSlotQueue = false; + m_SetDeleteThis = false; m_MaxPlayersPerTeam = 0; m_MaxPlayers = 0; @@ -67,21 +70,54 @@ BattleGround::BattleGround() m_TeamStartLocO[BG_TEAM_ALLIANCE] = 0; m_TeamStartLocO[BG_TEAM_HORDE] = 0; + m_ArenaTeamIds[BG_TEAM_ALLIANCE] = 0; + m_ArenaTeamIds[BG_TEAM_HORDE] = 0; + + m_ArenaTeamRatingChanges[BG_TEAM_ALLIANCE] = 0; + m_ArenaTeamRatingChanges[BG_TEAM_HORDE] = 0; + m_BgRaids[BG_TEAM_ALLIANCE] = NULL; m_BgRaids[BG_TEAM_HORDE] = NULL; m_PlayersCount[BG_TEAM_ALLIANCE] = 0; m_PlayersCount[BG_TEAM_HORDE] = 0; + + m_PrematureCountDown = false; + m_PrematureCountDown = 0; } BattleGround::~BattleGround() { + // remove objects and creatures + // (this is done automatically in mapmanager update, when the instance is reset after the reset time) + int size = m_BgCreatures.size(); + for(int i = 0; i < size; ++i) + { + DelCreature(i); + } + size = m_BgObjects.size(); + for(int i = 0; i < size; ++i) + { + DelObject(i); + } + // delete creature and go respawn times + WorldDatabase.PExecute("DELETE FROM creature_respawn WHERE instance = '%u'",GetInstanceID()); + WorldDatabase.PExecute("DELETE FROM gameobject_respawn WHERE instance = '%u'",GetInstanceID()); + // delete instance from db + CharacterDatabase.PExecute("DELETE FROM instance WHERE id = '%u'",GetInstanceID()); + // remove from battlegrounds + sBattleGroundMgr.RemoveBattleGround(GetInstanceID()); + // unload map + if(Map * map = MapManager::Instance().FindMap(GetMapId(), GetInstanceID())) + if(map->IsBattleGroundOrArena()) + ((BattleGroundMap*)map)->SetUnload(); + // remove from bg free slot queue + this->RemoveFromBGFreeSlotQueue(); } void BattleGround::Update(time_t diff) { - if(!GetPlayersSize() && !GetRemovedPlayersSize() && !GetReviveQueueSize()) //BG is empty return; @@ -188,6 +224,33 @@ void BattleGround::Update(time_t diff) m_ResurrectQueue.clear(); } + // if less then minimum players are in on one side, then start premature finish timer + if(GetStatus() == STATUS_IN_PROGRESS && !isArena() && sBattleGroundMgr.GetPrematureFinishTime() && (GetPlayersCountByTeam(ALLIANCE) < GetMinPlayersPerTeam() || GetPlayersCountByTeam(HORDE) < GetMinPlayersPerTeam())) + { + if(!m_PrematureCountDown) + { + m_PrematureCountDown = true; + m_PrematureCountDownTimer = sBattleGroundMgr.GetPrematureFinishTime(); + SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING); + } + else if(m_PrematureCountDownTimer < diff) + { + // time's up! + EndBattleGround(0); // noone wins + m_PrematureCountDown = false; + } + else + { + uint32 newtime = m_PrematureCountDownTimer - diff; + // announce every minute + if(m_PrematureCountDownTimer != sBattleGroundMgr.GetPrematureFinishTime() && newtime / 60000 != m_PrematureCountDownTimer / 60000) + SendMessageToAll(LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING); + m_PrematureCountDownTimer = newtime; + } + } + else if (m_PrematureCountDown) + m_PrematureCountDown = false; + if(GetStatus() == STATUS_WAIT_LEAVE) { // remove all players from battleground after 2 minutes @@ -239,7 +302,10 @@ void BattleGround::SendPacketToTeam(uint32 TeamID, WorldPacket *packet, Player * if(!self && sender == plr) continue; - if(plr->GetTeam() == TeamID) + uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + if(!team) team = plr->GetTeam(); + + if(team == TeamID) plr->GetSession()->SendPacket(packet); } } @@ -265,7 +331,10 @@ void BattleGround::PlaySoundToTeam(uint32 SoundID, uint32 TeamID) continue; } - if(plr->GetTeam() == TeamID) + uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + if(!team) team = plr->GetTeam(); + + if(team == TeamID) { sBattleGroundMgr.BuildPlaySoundPacket(&data, SoundID); plr->GetSession()->SendPacket(&data); @@ -285,7 +354,10 @@ void BattleGround::CastSpellOnTeam(uint32 SpellID, uint32 TeamID) continue; } - if(plr->GetTeam() == TeamID) + uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + if(!team) team = plr->GetTeam(); + + if(team == TeamID) plr->CastSpell(plr, SpellID, true); } } @@ -302,7 +374,10 @@ void BattleGround::RewardHonorToTeam(uint32 Honor, uint32 TeamID) continue; } - if(plr->GetTeam() == TeamID) + uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + if(!team) team = plr->GetTeam(); + + if(team == TeamID) UpdatePlayerScore(plr, SCORE_BONUS_HONOR, Honor); } } @@ -324,7 +399,10 @@ void BattleGround::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, continue; } - if(plr->GetTeam() == TeamID) + uint32 team = itr->second.Team;//GetPlayerTeam(plr->GetGUID()); + if(!team) team = plr->GetTeam(); + + if(team == TeamID) plr->ModifyFactionReputation(factionEntry, Reputation); } } @@ -345,30 +423,84 @@ void BattleGround::UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player void BattleGround::EndBattleGround(uint32 winner) { + this->RemoveFromBGFreeSlotQueue(); + + ArenaTeam * winner_arena_team = NULL; + ArenaTeam * loser_arena_team = NULL; + uint32 loser_rating = 0; + uint32 winner_rating = 0; WorldPacket data; Player *Source = NULL; const char *winmsg = ""; if(winner == ALLIANCE) { - winmsg = GetMangosString(LANG_BG_A_WINS); + if(isBattleGround()) + winmsg = GetMangosString(LANG_BG_A_WINS); + else + winmsg = GetMangosString(LANG_ARENA_GOLD_WINS); PlaySoundToAll(SOUND_ALLIANCE_WINS); // alliance wins sound SetWinner(WINNER_ALLIANCE); } - else + else if(winner == HORDE) { - winmsg = GetMangosString(LANG_BG_H_WINS); + if(isBattleGround()) + winmsg = GetMangosString(LANG_BG_H_WINS); + else + winmsg = GetMangosString(LANG_ARENA_GREEN_WINS); PlaySoundToAll(SOUND_HORDE_WINS); // horde wins sound SetWinner(WINNER_HORDE); } + else + { + SetWinner(3); + } SetStatus(STATUS_WAIT_LEAVE); m_EndTime = 0; + // arena rating calculation + if(isArena() && isRated()) + { + if(winner == ALLIANCE) + { + winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); + loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); + } + else if(winner == HORDE) + { + winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); + loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); + } + if(winner_arena_team && loser_arena_team) + { + loser_rating = loser_arena_team->GetStats().rating; + winner_rating = winner_arena_team->GetStats().rating; + int32 winner_change = winner_arena_team->WonAgainst(loser_rating); + int32 loser_change = loser_arena_team->LostAgainst(winner_rating); + sLog.outDebug("--- Winner rating: %u, Loser rating: %u, Winner change: %u, Losser change: %u ---", winner_rating, loser_rating, winner_change, loser_change); + if(winner == ALLIANCE) + { + SetArenaTeamRatingChangeForTeam(ALLIANCE, winner_change); + SetArenaTeamRatingChangeForTeam(HORDE, loser_change); + } + else + { + SetArenaTeamRatingChangeForTeam(HORDE, winner_change); + SetArenaTeamRatingChangeForTeam(ALLIANCE, loser_change); + } + } + else + { + SetArenaTeamRatingChangeForTeam(ALLIANCE, 0); + SetArenaTeamRatingChangeForTeam(HORDE, 0); + } + } + for(std::map::iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { Player *plr = objmgr.GetPlayer(itr->first); @@ -378,13 +510,29 @@ void BattleGround::EndBattleGround(uint32 winner) continue; } + // should remove spirit of redemption + if(plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) + plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); + if(!plr->isAlive()) { plr->ResurrectPlayer(1.0f); plr->SpawnCorpseBones(); } - if(plr->GetTeam() == winner) + uint32 team = itr->second.Team; + if(!team) team = plr->GetTeam(); + + // per player calculation + if(isArena() && isRated() && winner_arena_team && loser_arena_team) + { + if(team == winner) + winner_arena_team->MemberWon(plr,loser_rating); + else + loser_arena_team->MemberLost(plr,winner_rating); + } + + if(team == winner) { if(!Source) Source = plr; @@ -404,10 +552,28 @@ void BattleGround::EndBattleGround(uint32 winner) sBattleGroundMgr.BuildPvpLogDataPacket(&data, this); plr->GetSession()->SendPacket(&data); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_IN_PROGRESS, TIME_TO_AUTOREMOVE, GetStartTime()); plr->GetSession()->SendPacket(&data); } + if(isArena() && isRated() && winner_arena_team && loser_arena_team) + { + // update arena points only after increasing the player's match count! + //obsolete: winner_arena_team->UpdateArenaPointsHelper(); + //obsolete: loser_arena_team->UpdateArenaPointsHelper(); + // save the stat changes + winner_arena_team->SaveToDB(); + loser_arena_team->SaveToDB(); + // send updated arena team stats to players + // this way all arena team members will get notified, not only the ones who participated in this match + winner_arena_team->NotifyStatsChanged(); + loser_arena_team->NotifyStatsChanged(); + } + + // inform invited players about the removal + sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); + if(Source) { ChatHandler(Source).FillMessageData(&data, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, Source->GetGUID(), winmsg); @@ -558,12 +724,16 @@ void BattleGround::BlockMovement(Player *plr) void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket) { + uint32 team = GetPlayerTeam(guid); + bool participant = false; // Remove from lists/maps std::map::iterator itr = m_Players.find(guid); if(itr != m_Players.end()) { - UpdatePlayersCountByTeam(itr->second.Team, true); // -1 player + UpdatePlayersCountByTeam(team, true); // -1 player m_Players.erase(itr); + // check if the player was a participant of the match, or only entered through gm command (goname) + participant = true; } std::map::iterator itr2 = m_PlayerScores.find(guid); @@ -577,6 +747,10 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac Player *plr = objmgr.GetPlayer(guid); + // should remove spirit of redemption + if(plr && plr->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) + plr->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); + if(plr && !plr->isAlive()) // resurrect on exit { plr->ResurrectPlayer(1.0f); @@ -589,66 +763,106 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac { plr->ClearAfkReports(); - if(isArena()) + if(participant) // if the player was a match participant, remove auras, calc rating, update queue { - if(!sWorld.IsFFAPvPRealm()) - plr->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); - } + if(!team) team = plr->GetTeam(); - WorldPacket data; - if(SendPacket) - { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, plr->GetTeam(), plr->GetBattleGroundQueueIndex(m_TypeID), STATUS_NONE, 0, 0); - plr->GetSession()->SendPacket(&data); - } - - // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg - plr->RemoveBattleGroundQueueId(m_TypeID); - - DecreaseInvitedCount(plr->GetTeam()); - //we should update battleground queue, but only if bg isn't ending - if (GetQueueType() < MAX_BATTLEGROUND_QUEUES) - sBattleGroundMgr.m_BattleGroundQueues[GetTypeID()].Update(GetTypeID(), GetQueueType()); - - if(!plr->GetBattleGroundId()) - return; - - Group * group = plr->GetGroup(); - - // remove from raid group if exist - if(group && group == GetBgRaid(plr->GetTeam())) - { - if(!group->RemoveMember(guid, 0)) // group was disbanded + uint32 bgTypeId = GetTypeID(); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType()); + // if arena, remove the specific arena auras + if(isArena()) { - SetBgRaid(plr->GetTeam(), NULL); - delete group; + plr->RemoveArenaAuras(true); // removes debuffs / dots etc., we don't want the player to die after porting out + bgTypeId=BATTLEGROUND_AA; // set the bg type to all arenas (it will be used for queue refreshing) + + // summon old pet if there was one and there isn't a current pet + if(!plr->GetPet() && plr->GetTemporaryUnsummonedPetNumber()) + { + Pet* NewPet = new Pet; + if(!NewPet->LoadPetFromDB(plr, 0, (plr)->GetTemporaryUnsummonedPetNumber(), true)) + delete NewPet; + + (plr)->SetTemporaryUnsummonedPetNumber(0); + } + + if(isRated() && GetStatus() == STATUS_IN_PROGRESS) + { + //left a rated match while the encounter was in progress, consider as loser + ArenaTeam * winner_arena_team = 0; + ArenaTeam * loser_arena_team = 0; + if(team == HORDE) + { + winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); + loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); + } + else + { + winner_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(HORDE)); + loser_arena_team = objmgr.GetArenaTeamById(GetArenaTeamIdForTeam(ALLIANCE)); + } + if(winner_arena_team && loser_arena_team) + { + loser_arena_team->MemberLost(plr,winner_arena_team->GetRating()); + } + } } + + WorldPacket data; + if(SendPacket) + { + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, this, team, plr->GetBattleGroundQueueIndex(bgQueueTypeId), STATUS_NONE, 0, 0); + plr->GetSession()->SendPacket(&data); + } + + // this call is important, because player, when joins to battleground, this method is not called, so it must be called when leaving bg + plr->RemoveBattleGroundQueueId(bgQueueTypeId); + + DecreaseInvitedCount(team); + //we should update battleground queue, but only if bg isn't ending + if (GetQueueType() < MAX_BATTLEGROUND_QUEUES) + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, GetQueueType()); + + Group * group = plr->GetGroup(); + // remove from raid group if exist + if(group && group == GetBgRaid(team)) + { + if(!group->RemoveMember(guid, 0)) // group was disbanded + { + SetBgRaid(team, NULL); + delete group; + } + } + + // Let others know + sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); + SendPacketToTeam(team, &data, plr, false); } // Do next only if found in battleground plr->SetBattleGroundId(0); // We're not in BG. - - // Let others know - sBattleGroundMgr.BuildPlayerLeftBattleGroundPacket(&data, plr); - SendPacketToTeam(plr->GetTeam(), &data, plr, false); + // reset destination bg team + plr->SetBGTeam(0); if(Transport) { plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO()); - //sLog.outDetail("BATTLEGROUND: Sending %s to %f,%f,%f,%f", pl->GetName(), x,y,z,O); } // Log sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName()); } - /// there will be code which will add battleground to BGFreeSlotQueue , when battleground instance will exist - // we always should check if BG is in that queue before adding.. - - if(!GetPlayersSize()) + if(!GetPlayersSize() && !GetInvitedCount(HORDE) && !GetInvitedCount(ALLIANCE)) { - Reset(); + // if no players left AND no invitees left, set this bg to delete in next update + // direct deletion could cause crashes + m_SetDeleteThis = true; + // return to prevent addition to freeslotqueue + return; } + + // a player exited the battleground, so there are free slots. add to queue + this->AddToBGFreeSlotQueue(); } // this method is called when no players remains in battleground @@ -660,6 +874,8 @@ void BattleGround::Reset() SetStartTime(0); SetEndTime(0); SetLastResurrectTime(0); + SetArenaType(0); + SetRated(false); m_Events = 0; @@ -668,6 +884,7 @@ void BattleGround::Reset() m_InvitedAlliance = 0; m_InvitedHorde = 0; + m_InBGFreeSlotQueue = false; m_Players.clear(); m_PlayerScores.clear(); @@ -704,10 +921,11 @@ void BattleGround::AddPlayer(Player *plr) sBattleGroundMgr.BuildPlayerJoinedBattleGroundPacket(&data, plr); SendPacketToTeam(team, &data, plr, false); + // add arena specific auras if(isArena()) { plr->RemoveArenaSpellCooldowns(); - //plr->RemoveArenaAuras(); + plr->RemoveArenaAuras(); plr->RemoveAllEnchantments(TEMP_ENCHANTMENT_SLOT); if(team == ALLIANCE) // gold { @@ -726,6 +944,19 @@ void BattleGround::AddPlayer(Player *plr) plr->DestroyConjuredItems(true); + Pet* pet = plr->GetPet(); + if(pet) + { + if(pet->getPetType() == SUMMON_PET || pet->getPetType() == HUNTER_PET) + { + (plr)->SetTemporaryUnsummonedPetNumber(pet->GetCharmInfo()->GetPetNumber()); + (plr)->SetOldPetSpell(pet->GetUInt32Value(UNIT_CREATED_BY_SPELL)); + } + (plr)->RemovePet(NULL,PET_SAVE_NOT_IN_SLOT); + } + else + (plr)->SetTemporaryUnsummonedPetNumber(0); + if(GetStatus() == STATUS_WAIT_JOIN) // not started yet { plr->CastSpell(plr, SPELL_ARENA_PREPARATION, true); @@ -740,9 +971,6 @@ void BattleGround::AddPlayer(Player *plr) plr->CastSpell(plr, SPELL_PREPARATION, true); // reduces all mana cost of spells. } - if(isArena()) - plr->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_FFA_PVP); - // Log sLog.outDetail("BATTLEGROUND: Player %s joined the battle.", plr->GetName()); } @@ -750,13 +978,20 @@ void BattleGround::AddPlayer(Player *plr) /* This method should be called only once ... it adds pointer to queue */ void BattleGround::AddToBGFreeSlotQueue() { - sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this); + // make sure to add only once + if(!m_InBGFreeSlotQueue) + { + sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].push_front(this); + m_InBGFreeSlotQueue = true; + } } /* This method removes this battleground from free queue - it must be called when deleting battleground - not used now*/ void BattleGround::RemoveFromBGFreeSlotQueue() { - /* uncomment this code when battlegrounds will work like instances + // set to be able to re-add if needed + m_InBGFreeSlotQueue = false; + // uncomment this code when battlegrounds will work like instances for (std::deque::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].end(); ++itr) { if ((*itr)->GetInstanceID() == m_InstanceID) @@ -764,30 +999,69 @@ void BattleGround::RemoveFromBGFreeSlotQueue() sBattleGroundMgr.BGFreeSlotQueue[m_TypeID].erase(itr); return; } - }*/ + } } -/* -this method should decide, if we can invite new player of certain team to BG, it is based on BATTLEGROUND_STATUS -*/ -bool BattleGround::HasFreeSlotsForTeam(uint32 Team) const +// get the number of free slots for team +// works in similar way that HasFreeSlotsForTeam did, but this is needed for join as group +uint32 BattleGround::GetFreeSlotsForTeam(uint32 Team) const { - //if BG is starting ... invite anyone: + //if BG is starting ... invite anyone if (GetStatus() == STATUS_WAIT_JOIN) - return GetInvitedCount(Team) < GetMaxPlayersPerTeam(); + return (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; //if BG is already started .. do not allow to join too much players of one faction uint32 otherTeam; + uint32 otherIn; if (Team == ALLIANCE) + { otherTeam = GetInvitedCount(HORDE); + otherIn = GetPlayersCountByTeam(HORDE); + } else + { otherTeam = GetInvitedCount(ALLIANCE); + otherIn = GetPlayersCountByTeam(ALLIANCE); + } if (GetStatus() == STATUS_IN_PROGRESS) - return (GetInvitedCount(Team) <= otherTeam && GetInvitedCount(Team) < GetMaxPlayersPerTeam()); + { + // difference based on ppl invited (not necessarily entered battle) + // default: allow 0 + uint32 diff = 0; + // allow join one person if the sides are equal (to fill up bg to minplayersperteam) + if (otherTeam == GetInvitedCount(Team)) + diff = 1; + // allow join more ppl if the other side has more players + else if(otherTeam > GetInvitedCount(Team)) + diff = otherTeam - GetInvitedCount(Team); - return false; + // difference based on max players per team (don't allow inviting more) + uint32 diff2 = (GetInvitedCount(Team) < GetMaxPlayersPerTeam()) ? GetMaxPlayersPerTeam() - GetInvitedCount(Team) : 0; + + // difference based on players who already entered + // default: allow 0 + uint32 diff3 = 0; + // allow join one person if the sides are equal (to fill up bg minplayersperteam) + if (otherIn == GetPlayersCountByTeam(Team)) + diff3 = 1; + // allow join more ppl if the other side has more players + else if (otherIn > GetPlayersCountByTeam(Team)) + diff3 = otherIn - GetPlayersCountByTeam(Team); + // or other side has less than minPlayersPerTeam + else if (GetInvitedCount(Team) <= GetMinPlayersPerTeam()) + diff3 = GetMinPlayersPerTeam() - GetInvitedCount(Team) + 1; + + // return the minimum of the 3 differences + + // min of diff and diff 2 + diff = diff < diff2 ? diff : diff2; + + // min of diff, diff2 and diff3 + return diff < diff3 ? diff : diff3 ; + } + + return 0; } -/* this method isn't called already, it will be useful when more battlegrounds of one type will be available */ bool BattleGround::HasFreeSlots() const { return GetPlayersSize() < GetMaxPlayers(); @@ -813,9 +1087,13 @@ void BattleGround::UpdatePlayerScore(Player *Source, uint32 type, uint32 value) itr->second->HonorableKills += value; break; case SCORE_BONUS_HONOR: // Honor bonus - // reward honor instantly - if(Source->RewardHonor(NULL, 1, value)) - itr->second->BonusHonor += value; + // do not add honor in arenas + if(isBattleGround()) + { + // reward honor instantly + if(Source->RewardHonor(NULL, 1, value)) + itr->second->BonusHonor += value; + } break; //used only in EY, but in MSG_PVP_LOG_DATA opcode case SCORE_DAMAGE_DONE: // Damage Done @@ -871,15 +1149,26 @@ void BattleGround::RemovePlayerFromResurrectQueue(uint64 player_guid) bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime) { - GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(entry); - if(!goinfo) + Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); + if(!map) + return false; + + // must be created this way, adding to godatamap would add it to the base map of the instance + // 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)) { sLog.outErrorDb("Gameobject template %u not found in database! BattleGround not created!", entry); + sLog.outError("Cannot create gameobject template %u! BattleGround not created!", entry); + delete go; return false; } +/* + uint32 guid = go->GetGUIDLow(); - uint32 guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); - + // without this, UseButtonOrDoor caused the crash, since it tried to get go info from godata + // iirc that was changed, so adding to go data map is no longer required if that was the only function using godata from GameObject without checking if it existed GameObjectData& data = objmgr.NewGOData(guid); data.id = entry; @@ -893,13 +1182,13 @@ bool BattleGround::AddObject(uint32 type, uint32 entry, float x, float y, float data.rotation2 = rotation2; data.rotation3 = rotation3; data.spawntimesecs = respawnTime; + data.spawnMask = 1; data.animprogress = 100; data.go_state = 1; - data.spawnMask = 1; - objmgr.AddGameobjectToGrid(guid, &data); - - m_BgObjects[type] = MAKE_NEW_GUID(guid, entry, HIGHGUID_GAMEOBJECT); - +*/ + // add to world, so it can be later looked up from HashMapHolder + go->AddToWorld(); + m_BgObjects[type] = go->GetGUID(); return true; } @@ -941,6 +1230,9 @@ void BattleGround::DoorOpen(uint32 type) void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime) { + Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); + if(!map) + return; if( respawntime == 0 ) { GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); @@ -949,30 +1241,27 @@ void BattleGround::SpawnBGObject(uint32 type, uint32 respawntime) //we need to change state from GO_JUST_DEACTIVATED to GO_READY in case battleground is starting again if( obj->getLootState() == GO_JUST_DEACTIVATED ) obj->SetLootState(GO_READY); - obj->Respawn(); + obj->SetRespawnTime(0); + map->Add(obj); } - else - objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, 0); } else { GameObject *obj = HashMapHolder::Find(m_BgObjects[type]); if(obj) { + map->Add(obj); obj->SetRespawnTime(respawntime); obj->SetLootState(GO_JUST_DEACTIVATED); } - else - objmgr.SaveGORespawnTime(GUID_LOPART(m_BgObjects[type]), 0, time(NULL) + respawntime); } } -Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o) +Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime) { - // note: this should normally be FindMap - // but it's a hack to allow the battlegrounds to initialize at server startup - Map * map = MapManager::Instance().GetMap(GetMapId(), 0); - if(!map) return NULL; + Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceID()); + if(!map) + return NULL; Creature* pCreature = new Creature; if (!pCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), map, entry, teamval)) @@ -996,9 +1285,39 @@ Creature* BattleGround::AddCreature(uint32 entry, uint32 type, uint32 teamval, f map->Add(pCreature); m_BgCreatures[type] = pCreature->GetGUID(); + return pCreature; } +/* +void BattleGround::SpawnBGCreature(uint32 type, uint32 respawntime) +{ + Map * map = MapManager::Instance().FindMap(GetMapId(),GetInstanceId()); + if(!map) + return false; + if(respawntime == 0) + { + Creature *obj = HashMapHolder::Find(m_BgCreatures[type]); + if(obj) + { + //obj->Respawn(); // bugged + obj->SetRespawnTime(0); + objmgr.SaveCreatureRespawnTime(obj->GetGUIDLow(), GetInstanceID(), 0); + map->Add(obj); + } + } + else + { + Creature *obj = HashMapHolder::Find(m_BgCreatures[type]); + if(obj) + { + obj->setDeathState(DEAD); + obj->SetRespawnTime(respawntime); + map->Add(obj); + } + } +} +*/ bool BattleGround::DelCreature(uint32 type) { Creature *cr = HashMapHolder::Find(m_BgCreatures[type]); @@ -1079,8 +1398,11 @@ void BattleGround::SendMessageToAll(int32 entry) void BattleGround::EndNow() { + RemoveFromBGFreeSlotQueue(); SetStatus(STATUS_WAIT_LEAVE); SetEndTime(TIME_TO_AUTOREMOVE); + // inform invited players about the removal + sBattleGroundMgr.m_BattleGroundQueues[sBattleGroundMgr.BGQueueTypeId(GetTypeID(), GetArenaType())].BGEndedRemoveInvites(this); } // Battleground messages are localized using the dbc lang, they are not client language dependent @@ -1158,3 +1480,28 @@ void BattleGround::HandleKillPlayer( Player *player, Player *killer ) // to be able to remove insignia player->SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE ); } + +// return the player's team based on battlegroundplayer info +// used in same faction arena matches mainly +uint32 BattleGround::GetPlayerTeam(uint64 guid) +{ + std::map::const_iterator itr = m_Players.find(guid); + if(itr!=m_Players.end()) + return itr->second.Team; + return 0; +} + +uint32 BattleGround::GetAlivePlayersCountByTeam(uint32 Team) const +{ + int count = 0; + for(std::map::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) + { + if(itr->second.Team == Team) + { + Player * pl = objmgr.GetPlayer(itr->first); + if(pl && pl->isAlive()) + ++count; + } + } + return count; +} diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index 9e41e661b..bff2eb64d 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -18,6 +18,7 @@ #ifndef __BATTLEGROUND_H #define __BATTLEGROUND_H +#define ARENA_PATCH #include "Common.h" #include "WorldPacket.h" @@ -83,7 +84,7 @@ enum BattleGroundTimeIntervals { RESURRECTION_INTERVAL = 30000, // ms REMIND_INTERVAL = 30000, // ms - INVITE_ACCEPT_WAIT_TIME = 120000, // ms + INVITE_ACCEPT_WAIT_TIME = 80000, // ms TIME_TO_AUTOREMOVE = 120000, // ms MAX_OFFLINE_TIME = 300000, // ms START_DELAY0 = 120000, // ms @@ -143,6 +144,18 @@ enum BattleGroundTypeId 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 +{ + BATTLEGROUND_QUEUE_AV = 1, + BATTLEGROUND_QUEUE_WS = 2, + BATTLEGROUND_QUEUE_AB = 3, + BATTLEGROUND_QUEUE_EY = 4, + BATTLEGROUND_QUEUE_2v2 = 5, + BATTLEGROUND_QUEUE_3v3 = 6, + BATTLEGROUND_QUEUE_5v5 = 7, +}; + enum ScoreType { SCORE_KILLING_BLOWS = 1, @@ -195,6 +208,20 @@ enum BattleGroundTeamId BG_TEAM_HORDE = 1 }; +enum BattleGroundJoinError +{ + BG_JOIN_ERR_OK = 0, + BG_JOIN_ERR_OFFLINE_MEMBER = 1, + BG_JOIN_ERR_GROUP_TOO_MANY = 2, + BG_JOIN_ERR_MIXED_FACTION = 3, + BG_JOIN_ERR_MIXED_LEVELS = 4, + BG_JOIN_ERR_MIXED_ARENATEAM = 5, + BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE = 6, + BG_JOIN_ERR_GROUP_DESERTER = 7, + BG_JOIN_ERR_ALL_QUEUES_USED = 8, + BG_JOIN_ERR_GROUP_NOT_ENOUGH = 9 +}; + class BattleGroundScore { public: @@ -224,6 +251,7 @@ class BattleGround public: /* Construction */ 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 bool SetupBattleGround() // must be implemented in BG subclass @@ -296,6 +324,7 @@ class BattleGround } bool HasFreeSlotsForTeam(uint32 Team) const; bool HasFreeSlots() const; + uint32 GetFreeSlotsForTeam(uint32 Team) const; bool isArena() const { return m_IsArena; } bool isBattleGround() const { return !m_IsArena; } @@ -366,6 +395,7 @@ class BattleGround uint8 GetTeamIndexByTeamId(uint32 Team) const { return Team == ALLIANCE ? BG_TEAM_ALLIANCE : BG_TEAM_HORDE; } uint32 GetPlayersCountByTeam(uint32 Team) const { return m_PlayersCount[GetTeamIndexByTeamId(Team)]; } + uint32 GetAlivePlayersCountByTeam(uint32 Team) const; // used in arenas to correctly handle death in spirit of redemption / last stand etc. (killer = killed) cases void UpdatePlayersCountByTeam(uint32 Team, bool remove) { if(remove) @@ -374,6 +404,12 @@ class BattleGround ++m_PlayersCount[GetTeamIndexByTeamId(Team)]; } + // used for rated arena battles + void SetArenaTeamIdForTeam(uint32 Team, uint32 ArenaTeamId) { m_ArenaTeamIds[GetTeamIndexByTeamId(Team)] = ArenaTeamId; } + uint32 GetArenaTeamIdForTeam(uint32 Team) const { return m_ArenaTeamIds[GetTeamIndexByTeamId(Team)]; } + void SetArenaTeamRatingChangeForTeam(uint32 Team, int32 RatingChange) { m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)] = RatingChange; } + int32 GetArenaTeamRatingChangeForTeam(uint32 Team) const { return m_ArenaTeamRatingChanges[GetTeamIndexByTeamId(Team)]; } + /* Triggers handle */ // must be implemented in BG subclass virtual void HandleAreaTrigger(Player* /*Source*/, uint32 /*Trigger*/) {} @@ -390,6 +426,7 @@ class BattleGround virtual WorldSafeLocsEntry const* GetClosestGraveYard(float /*x*/, float /*y*/, float /*z*/, uint32 /*team*/) { return NULL; } virtual void AddPlayer(Player *plr); // must be implemented in BG subclass + virtual void RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPacket); // can be extended in in BG subclass @@ -402,7 +439,8 @@ class BattleGround BGCreatures m_BgCreatures; void SpawnBGObject(uint32 type, uint32 respawntime); bool AddObject(uint32 type, uint32 entry, float x, float y, float z, float o, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime = 0); - Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o); +// void SpawnBGCreature(uint32 type, uint32 respawntime); + Creature* AddCreature(uint32 entry, uint32 type, uint32 teamval, float x, float y, float z, float o, uint32 respawntime = 0); bool DelCreature(uint32 type); bool DelObject(uint32 type); bool AddSpiritGuide(uint32 type, float x, float y, float z, float o, uint32 team); @@ -411,6 +449,13 @@ class BattleGround void DoorClose(uint32 type); const char *GetMangosString(int32 entry); + virtual bool HandlePlayerUnderMap(Player * plr) {return false;} + + // since arenas can be AvA or Hvh, we have to get the "temporary" team of a player + uint32 GetPlayerTeam(uint64 guid); + + void SetDeleteThis() {m_SetDeleteThis = true;} + protected: //this method is called, when BG cannot spawn its own spirit guide, or something is wrong, It correctly ends BattleGround void EndNow(); @@ -443,6 +488,8 @@ class BattleGround uint32 m_LastResurrectTime; uint32 m_Queue_type; uint8 m_ArenaType; // 2=2v2, 3=3v3, 5=5v5 + bool m_InBGFreeSlotQueue; // used to make sure that BG is only once inserted into the BattleGroundMgr.BGFreeSlotQueue[bgTypeId] deque + bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave // this variable is not used .... it can be found in many other ways... but to store it in BG object instance is useless //uint8 m_BattleGroundType; // 3=BG, 4=arena //instead of uint8 (in previous line) is bool used @@ -450,6 +497,8 @@ class BattleGround uint8 m_Winner; // 0=alliance, 1=horde, 2=none int32 m_StartDelayTime; bool m_IsRated; // is this battle rated? + bool m_PrematureCountDown; + uint32 m_PrematureCountDownTimer; char const *m_Name; /* Player lists */ @@ -468,6 +517,11 @@ class BattleGround /* Players count by team */ uint32 m_PlayersCount[2]; + /* Arena team ids by team */ + uint32 m_ArenaTeamIds[2]; + + int32 m_ArenaTeamRatingChanges[2]; + /* Limits */ uint32 m_LevelMin; uint32 m_LevelMax; diff --git a/src/game/BattleGroundAB.cpp b/src/game/BattleGroundAB.cpp index dcf23ccff..5200a3f5f 100644 --- a/src/game/BattleGroundAB.cpp +++ b/src/game/BattleGroundAB.cpp @@ -50,6 +50,13 @@ void BattleGroundAB::Update(time_t diff) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } + sLog.outDebug("Arathi Basin: entering state STATUS_WAIT_JOIN ..."); // despawn banners, auras and buffs @@ -377,6 +384,7 @@ void BattleGroundAB::_NodeOccupied(uint8 node,Team team) { if( !AddSpiritGuide(node, BG_AB_SpiritGuidePos[node][0], BG_AB_SpiritGuidePos[node][1], BG_AB_SpiritGuidePos[node][2], BG_AB_SpiritGuidePos[node][3], team) ) sLog.outError("Failed to spawn spirit guide! point: %u, team: %u,", node, team); +// SpawnBGCreature(node,RESPAWN_IMMEDIATELY); uint8 capturedNodes = 0; for (uint8 i = 0; i < BG_AB_DYNAMIC_NODES_COUNT; ++i) diff --git a/src/game/BattleGroundBE.cpp b/src/game/BattleGroundBE.cpp index 4ad71988e..81e47c721 100644 --- a/src/game/BattleGroundBE.cpp +++ b/src/game/BattleGroundBE.cpp @@ -47,6 +47,12 @@ void BattleGroundBE::Update(time_t diff) if (!(m_Events & 0x01)) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } for(uint32 i = BG_BE_OBJECT_DOOR_1; i <= BG_BE_OBJECT_DOOR_4; i++) SpawnBGObject(i, RESPAWN_IMMEDIATELY); @@ -86,6 +92,11 @@ void BattleGroundBE::Update(time_t diff) for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) if(Player *plr = objmgr.GetPlayer(itr->first)) plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); + + if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } } @@ -102,11 +113,23 @@ void BattleGroundBE::AddPlayer(Player *plr) BattleGroundBEScore* sc = new BattleGroundBEScore; m_PlayerScores[plr->GetGUID()] = sc; + + UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); } void BattleGroundBE::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) { + if(GetStatus() == STATUS_WAIT_LEAVE) + return; + UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); + + if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer) @@ -120,17 +143,27 @@ void BattleGroundBE::HandleKillPlayer(Player *player, Player *killer) return; } - BattleGround::HandleKillPlayer(player, killer); + BattleGround::HandleKillPlayer(player,killer); - uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); + UpdateWorldState(0x9f1, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0x9f0, GetAlivePlayersCountByTeam(HORDE)); - ++m_TeamKills[killer_team_index]; // add kills to killer's team - - if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) + if(!GetAlivePlayersCountByTeam(ALLIANCE)) { // all opponents killed - EndBattleGround(killer->GetTeam()); + EndBattleGround(HORDE); } + else if(!GetAlivePlayersCountByTeam(HORDE)) + { + // all opponents killed + EndBattleGround(ALLIANCE); + } +} + +bool BattleGroundBE::HandlePlayerUnderMap(Player *player) +{ + player->TeleportTo(GetMapId(),6238.930176,262.963470,0.889519,player->GetOrientation(),false); + return true; } void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger) @@ -159,10 +192,16 @@ void BattleGroundBE::HandleAreaTrigger(Player *Source, uint32 Trigger) // HandleTriggerBuff(buff_guid,Source); } +void BattleGroundBE::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(0x9f1) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7 + data << uint32(0x9f0) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8 + data << uint32(0x9f3) << uint32(1); // 9 +} + void BattleGroundBE::ResetBGSubclass() { - m_TeamKills[BG_TEAM_ALLIANCE] = 0; - m_TeamKills[BG_TEAM_HORDE] = 0; + } bool BattleGroundBE::SetupBattleGround() diff --git a/src/game/BattleGroundBE.h b/src/game/BattleGroundBE.h index f74f0a648..df46efbfd 100644 --- a/src/game/BattleGroundBE.h +++ b/src/game/BattleGroundBE.h @@ -64,12 +64,11 @@ class BattleGroundBE : public BattleGround void HandleAreaTrigger(Player *Source, uint32 Trigger); bool SetupBattleGround(); void ResetBGSubclass(); + virtual void FillInitialWorldStates(WorldPacket &d); void HandleKillPlayer(Player* player, Player *killer); + bool HandlePlayerUnderMap(Player * plr); /* Scorekeeping */ void UpdatePlayerScore(Player *Source, uint32 type, uint32 value); - - private: - uint32 m_TeamKills[2]; // count of kills for each team }; #endif diff --git a/src/game/BattleGroundEY.cpp b/src/game/BattleGroundEY.cpp index 241ad5b98..279816b34 100644 --- a/src/game/BattleGroundEY.cpp +++ b/src/game/BattleGroundEY.cpp @@ -54,9 +54,18 @@ void BattleGroundEY::Update(time_t diff) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } + SpawnBGObject(BG_EY_OBJECT_DOOR_A, RESPAWN_IMMEDIATELY); SpawnBGObject(BG_EY_OBJECT_DOOR_H, RESPAWN_IMMEDIATELY); +// SpawnBGCreature(EY_SPIRIT_MAIN_ALLIANCE, RESPAWN_IMMEDIATELY); +// SpawnBGCreature(EY_SPIRIT_MAIN_HORDE, RESPAWN_IMMEDIATELY); for(uint32 i = BG_EY_OBJECT_A_BANNER_FEL_REALVER_CENTER; i < BG_EY_OBJECT_MAX; ++i) SpawnBGObject(i, RESPAWN_ONE_DAY); @@ -572,7 +581,17 @@ void BattleGroundEY::HandleKillPlayer(Player *player, Player *killer) void BattleGroundEY::EventPlayerDroppedFlag(Player *Source) { - // Drop allowed in any BG state + if(GetStatus() != STATUS_IN_PROGRESS) + { + // if not running, do not cast things at the dropper player, neither send unnecessary messages + // just take off the aura + if(IsFlagPickedup() && GetFlagPickerGUID() == Source->GetGUID()) + { + SetFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_EY_NETHERSTORM_FLAG_SPELL); + } + return; + } if(!IsFlagPickedup()) return; @@ -744,6 +763,8 @@ void BattleGroundEY::EventTeamCapturedPoint(Player *Source, uint32 Point) sLog.outError("BatteGroundEY: Failed to spawn spirit guide! point: %u, team: %u, graveyard_id: %u", Point, Team, m_CapturingPointTypes[Point].GraveYardId); +// SpawnBGCreature(Point,RESPAWN_IMMEDIATELY); + UpdatePointsIcons(Team, Point); UpdatePointsCount(Team); } diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 3b744f043..13fd1d539 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -26,9 +26,11 @@ #include "MapManager.h" #include "ObjectAccessor.h" #include "Object.h" +#include "Chat.h" #include "BattleGroundMgr.h" #include "BattleGroundWS.h" #include "BattleGround.h" +#include "ArenaTeam.h" #include "Language.h" void WorldSession::HandleBattleGroundHelloOpcode( WorldPacket & recv_data ) @@ -76,18 +78,25 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) uint32 bgTypeId; uint32 instanceId; uint8 joinAsGroup; + Group * grp; recv_data >> guid; // battlemaster guid recv_data >> bgTypeId; // battleground type id (DBC id) recv_data >> instanceId; // instance id, 0 if First Available selected recv_data >> joinAsGroup; // join as group - sLog.outDebug( "WORLD: Recvd CMSG_BATTLEMASTER_JOIN Message from: " I64FMT " for BG (Type: %u)", guid, bgTypeId); - - if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? + if(bgTypeId >= MAX_BATTLEGROUND_TYPES) + { + sLog.outError("Battleground: invalid bgtype received. possible cheater? player guid %u",_player->GetGUIDLow()); return; + } - // ignore if we already in BG or BG queue + 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); + + // ignore if player is already in BG if(_player->InBattleGround()) return; @@ -98,74 +107,82 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) if(!unit->isBattleMaster()) // it's not battlemaster return; - // check Deserter debuff - if( !_player->CanJoinToBattleground() ) + // get bg instance or bg template if instance not found + BattleGround * bg = 0; + if(instanceId) + BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); + + if(!bg && !(bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId))) { - WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); - data << (uint32) 0xFFFFFFFE; - _player->GetSession()->SendPacket(&data); + sLog.outError("Battleground: no available bg / template found"); return; } - // check existence - BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); - if(!bg) - return; - - if(joinAsGroup && _player->GetGroup()) + // check queueing conditions + if(!joinAsGroup) { - Group *grp = _player->GetGroup(); + // check Deserter debuff + if( !_player->CanJoinToBattleground() ) + { + WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); + data << (uint32) 0xFFFFFFFE; + _player->GetSession()->SendPacket(&data); + return; + } + // check if already in queue + if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) + //player is already in this queue + return; + // check if has free queue slots + if(!_player->HasFreeBattleGroundQueueId()) + return; + } + else + { + grp = _player->GetGroup(); + // no group found, error + if(!grp) + return; + uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, 0, bg->GetMaxPlayersPerTeam(), false, 0); + if (err != BG_JOIN_ERR_OK) + { + SendBattleGroundOrArenaJoinError(err); + return; + } + } + // if we're here, then the conditions to join a bg are met. We can proceed in joining. + + // _player->GetGroup() was already checked, grp is already initialized + if(joinAsGroup /* && _player->GetGroup()*/) + { + sLog.outDebug("Battleground: the following players are joining as group:"); + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, 0, false, 0); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); - if(!member) continue; + if(!member) continue; // this should never happen - if( !member->CanJoinToBattleground() ) - { - WorldPacket data(SMSG_GROUP_JOINED_BATTLEGROUND, 4); - data << (uint32) 0xFFFFFFFE; - _player->GetSession()->SendPacket(&data); - continue; - } - if (member->InBattleGroundQueueForBattleGroundType(bgTypeId)) - //player is already in this queue - continue; - - WorldPacket data; - // add to queue - uint32 queueSlot = member->AddBattleGroundQueueId(bgTypeId); - if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) - { - // fill data packet - //member->GetSession()->SendPacket(data); - continue; - } + uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId); // add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); + WorldPacket data; // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); member->GetSession()->SendPacket(&data); sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); - sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(member, bgTypeId); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); + sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } + sLog.outDebug("Battleground: group end"); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel()); } else { - if (_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) - //player is already in this queue - return; - uint32 queueSlot = _player->AddBattleGroundQueueId(bgTypeId); - if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) - { - WorldPacket data; - // fill data packet - //SendPacket(data); - return; - } - + // already checked if queueSlot is valid, now just get it + uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); @@ -173,7 +190,11 @@ void WorldSession::HandleBattleGroundJoinOpcode( WorldPacket & recv_data ) // send status packet (in queue) sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); SendPacket(&data); - sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].AddPlayer(_player, bgTypeId); + + 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()); + sLog.outDebug("Battleground: player joined queue for bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } } @@ -247,12 +268,11 @@ void WorldSession::HandleBattleGroundListOpcode( WorldPacket &recv_data ) uint32 bgTypeId; recv_data >> bgTypeId; // id from DBC - if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? - return; - - // can't be received if player not in BG queue - if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) + if(bgTypeId >= MAX_BATTLEGROUND_TYPES) + { + sLog.outError("Battleground: invalid bgtype received."); return; + } BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); @@ -270,80 +290,201 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) sLog.outDebug( "WORLD: Recvd CMSG_BATTLEFIELD_PORT Message"); - uint8 unk1; + 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 uint16 unk; // 0x1F90 constant? uint8 action; // enter battle 0x1, leave queue 0x0 - recv_data >> unk1 >> unk2 >> bgTypeId >> unk >> action; + recv_data >> type >> unk2 >> bgTypeId >> unk >> action; - if(bgTypeId >= MAX_BATTLEGROUND_TYPES) // cheating? - return; - - if(!_player->InBattleGroundQueueForBattleGroundType(bgTypeId)) - return; - - BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); - if(!bg) - return; - - uint32 queueSlot = 0; - WorldPacket data; - switch(action) + if(bgTypeId >= MAX_BATTLEGROUND_TYPES) { - case 1: // port to battleground - // cheating? - if(!_player->IsInvitedForBattleGroundType(bgTypeId)) - return; - - // check if player is not deserter - if( !_player->CanJoinToBattleground() ) + sLog.outError("Battleground: invalid bgtype received."); + // 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) + if(_player->InBattleGroundQueue()) + { + // update all queues, send invitation info if player is invited, queue info if queued + for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { - WorldPacket data2; - data2.Initialize(SMSG_GROUP_JOINED_BATTLEGROUND, 4); - data2 << (uint32) 0xFFFFFFFE; - SendPacket(&data2); - return; + uint32 queue_id = _player->GetBattleGroundQueueId(i); + if(!queue_id) + continue; + BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); + // if the player is not in queue, contine + if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) + continue; + + // no group information, this should never happen + if(!itrPlayerStatus->second.GroupInfo) + continue; + + BattleGround * bg = NULL; + + // get possibly needed data from groupinfo + bgTypeId = itrPlayerStatus->second.GroupInfo->BgTypeId; + uint8 arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; + uint8 israted = itrPlayerStatus->second.GroupInfo->IsRated; + uint8 status = 0; + + + if(!itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID) + { + // not invited to bg, get template + bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + status = STATUS_WAIT_QUEUE; + } + else + { + // get the bg we're invited to + BattleGround * bg = sBattleGroundMgr.GetBattleGround(itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID); + status = STATUS_WAIT_JOIN; + } + + // if bg not found, then continue + if(!bg) + continue; + + // don't invite if already in the instance + if(_player->InBattleGround() && _player->GetBattleGround() && _player->GetBattleGround()->GetInstanceID() == bg->GetInstanceID()) + continue; + + // re - invite player with proper data + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, itrPlayerStatus->second.GroupInfo->Team?itrPlayerStatus->second.GroupInfo->Team:_player->GetTeam(), i, status, INVITE_ACCEPT_WAIT_TIME, 0, arenatype, israted); + SendPacket(&data); } + } + return; + } - // if the player is dead, resurrect him before teleport - if(!_player->isAlive()) - { - _player->ResurrectPlayer(1.0f); - _player->SpawnCorpseBones(); - } + uint32 bgQueueTypeId = 0; + // get the bg what we were invited to + BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus; + bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId,type); + itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); - // leave current group - _player->RemoveFromGroup(); + if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) + { + sLog.outError("Battleground: itrplayerstatus not found."); + return; + } + instanceId = itrPlayerStatus->second.GroupInfo->IsInvitedToBGInstanceGUID; - // packet to player about BG status - queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); - _player->GetSession()->SendPacket(&data); + // if action == 1, then instanceId is _required_ + if(!instanceId && action == 1) + { + sLog.outError("Battleground: instance not found."); + return; + } - // remove battleground queue status from BGmgr - sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), false); + BattleGround *bg = sBattleGroundMgr.GetBattleGround(instanceId); - // this is still needed here if battleground "jumping" shouldn't add deserter debuff - // also this required to prevent stuck at old battleground after SetBattleGroundId set to new - if (BattleGround *currentBg = _player->GetBattleGround()) - currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); + // bg template might and must be used in case of leaving queue, when instance is not created yet + if(!bg && action == 0) + bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); - _player->SetBattleGroundId(bg->GetTypeID()); - sBattleGroundMgr.SendToBattleGround(_player, bgTypeId); - bg->AddPlayer(_player); - break; - case 0: // leave queue - queueSlot = _player->GetBattleGroundQueueIndex(bgTypeId); - _player->RemoveBattleGroundQueueId(bgTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); - sBattleGroundMgr.m_BattleGroundQueues[bgTypeId].RemovePlayer(_player->GetGUID(), true); - SendPacket(&data); - break; - default: - sLog.outError("Battleground port: unknown action %u", action); - break; + if(!bg) + { + sLog.outError("Battleground: bg not found."); + return; + } + + bgTypeId = bg->GetTypeID(); + + if(_player->InBattleGroundQueue()) + { + uint32 queueSlot = 0; + uint32 team = 0; + uint32 arenatype = 0; + uint32 israted = 0; + uint32 rating = 0; + uint32 opponentsRating = 0; + // get the team info from the queue + BattleGroundQueue::QueuedPlayersMap::iterator pitr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); + if(pitr !=sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end() + && pitr->second.GroupInfo ) + { + team = pitr->second.GroupInfo->Team; + arenatype = pitr->second.GroupInfo->ArenaType; + israted = pitr->second.GroupInfo->IsRated; + rating = pitr->second.GroupInfo->ArenaTeamRating; + opponentsRating = pitr->second.GroupInfo->OpponentsTeamRating; + } + else + { + sLog.outError("Battleground: Invalid player queue info!"); + return; + } + WorldPacket data; + switch(action) + { + case 1: // port to battleground + if(!_player->IsInvitedForBattleGroundQueueType(bgQueueTypeId)) + return; // cheating? + // resurrect the player + if(!_player->isAlive()) + { + _player->ResurrectPlayer(1.0f); + _player->SpawnCorpseBones(); + } + // stop taxi flight at port + if(_player->isInFlight()) + { + _player->GetMotionMaster()->MovementExpired(); + _player->m_taxi.ClearTaxiDestinations(); + } + _player->RemoveFromGroup(); + queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); + _player->GetSession()->SendPacket(&data); + // remove battleground queue status from BGmgr + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), false); + // this is still needed here if battleground "jumping" shouldn't add deserter debuff + // also this required to prevent stuck at old battleground after SetBattleGroundId set to new + if( BattleGround *currentBg = _player->GetBattleGround() ) + currentBg->RemovePlayerAtLeave(_player->GetGUID(), false, true); + + // set the destination instance id + _player->SetBattleGroundId(bg->GetInstanceID()); + // set the destination team + _player->SetBGTeam(team); + // bg->HandleBeforeTeleportToBattleGround(_player); + sBattleGroundMgr.SendToBattleGround(_player, instanceId); + // add only in HandleMoveWorldPortAck() + // 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 + queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); + /* + if player leaves rated arena match before match start, it is counted as he played but he lost + */ + if (israted) + { + ArenaTeam * at = objmgr.GetArenaTeamById(team); + if (at) + { + sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u, because he has left queue!", GUID_LOPART(_player->GetGUID()), opponentsRating); + at->MemberLost(_player, opponentsRating); + at->SaveToDB(); + } + } + _player->RemoveBattleGroundQueueId(bgQueueTypeId); // must be called this way, because if you move this call to queue->removeplayer, it causes bugs + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(_player->GetGUID(), true); + // player left queue, we should update it, maybe now his group fits in + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId,_player->GetBattleGroundQueueIdFromLevel(),arenatype,israted,rating); + SendPacket(&data); + sLog.outDebug("Battleground: player %s (%u) left queue for bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetTypeID(),bgQueueTypeId); + break; + default: + sLog.outError("Battleground port: unknown action %u", action); + break; + } } } @@ -384,7 +525,8 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) BattleGround *bg = _player->GetBattleGround(); if(bg) { - uint32 queueSlot = _player->GetBattleGroundQueueIndex(bg->GetTypeID()); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); if((bg->GetStatus() <= STATUS_IN_PROGRESS)) { sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_IN_PROGRESS, 0, bg->GetStartTime()); @@ -392,15 +534,25 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) } for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { - uint32 queue_id = _player->GetBattleGroundQueueId(i); - if (i == queueSlot || !queue_id) + 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 isRated = 0; + if (i == queueSlot || !queue_id) // we need to get the instance ids continue; - BattleGround *bg2 = sBattleGroundMgr.GetBattleGround(queue_id); + BattleGroundQueue::QueuedPlayersMap::iterator itrPlayerStatus = sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].find(_player->GetGUID()); + if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) + continue; + if(itrPlayerStatus->second.GroupInfo) + { + arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; + isRated = itrPlayerStatus->second.GroupInfo->IsRated; + } + BattleGround *bg2 = sBattleGroundMgr.GetBattleGroundTemplate(sBattleGroundMgr.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 //this call nulls all timers for client : - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0,arenatype,isRated); SendPacket(&data); } } @@ -411,16 +563,36 @@ void WorldSession::HandleBattlefieldStatusOpcode( WorldPacket & /*recv_data*/ ) // we should update all queues? .. i'm not sure if this code is correct for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { - if(uint32 queue_id = _player->GetBattleGroundQueueId(i)) + uint32 queue_id = _player->GetBattleGroundQueueId(i); + if(!queue_id) + continue; + uint32 bgTypeId = sBattleGroundMgr.BGTemplateId(queue_id); + uint8 arenatype = sBattleGroundMgr.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()); + if(itrPlayerStatus == sBattleGroundMgr.m_BattleGroundQueues[queue_id].m_QueuedPlayers[_player->GetBattleGroundQueueIdFromLevel()].end()) + continue; + if(itrPlayerStatus->second.GroupInfo) { - if(BattleGround *bg = sBattleGroundMgr.GetBattleGround(queue_id)) - { - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0); - SendPacket(&data); - } + arenatype = itrPlayerStatus->second.GroupInfo->ArenaType; + isRated = itrPlayerStatus->second.GroupInfo->IsRated; + } + if(bg && queue_id) + { + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), i, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); + SendPacket(&data); } } } +/* else // not sure if it needed... + { + for (uint32 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + { + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, NULL, _player->GetTeam(),i , STATUS_NONE, 0, 0); + SendPacket(&data); + } + }*/ } void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data ) @@ -480,16 +652,12 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) if(_player->InBattleGround()) return; - for(int qId = 0; qId < PLAYER_MAX_BATTLEGROUND_QUEUES; ++qId) - { - if(_player->GetBattleGroundQueueId(qId) != 0) - return; - } - uint64 guid; // arena Battlemaster guid uint8 type; // 2v2, 3v3 or 5v5 uint8 asGroup; // asGroup uint8 isRated; // isRated + Group * grp; + recv_data >> guid >> type >> asGroup >> isRated; Creature *unit = ObjectAccessor::GetCreature(*_player, guid); @@ -500,6 +668,7 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) return; uint8 arenatype = 0; + uint32 arenaRating = 0; switch(type) { @@ -517,88 +686,118 @@ void WorldSession::HandleBattleGroundArenaJoin( WorldPacket & recv_data ) return; } - if(isRated && !_player->GetArenaTeamId(type)) // player not in arena team of that size + //check existance + BattleGround* bg = NULL; + if( !(bg = sBattleGroundMgr.GetBattleGroundTemplate(BATTLEGROUND_AA)) ) { - _player->GetSession()->SendNotInArenaTeamPacket(arenatype); + sLog.outError("Battleground: template bg (all arenas) not found"); return; } - if(asGroup && !_player->GetGroup()) // player not in group - return; + uint8 bgTypeId = bg->GetTypeID(); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); - // check existence - BattleGround *bg = sBattleGroundMgr.GetBattleGround(BATTLEGROUND_AA); - if(!bg) - return; - - bg->SetArenaType(arenatype); - bg->SetRated(isRated); - - if(asGroup && _player->GetGroup()) + // check queueing conditions + if(!asGroup) { - Group *grp = _player->GetGroup(); + // check if already in queue + if (_player->GetBattleGroundQueueIndex(bgQueueTypeId) < PLAYER_MAX_BATTLEGROUND_QUEUES) + //player is already in this queue + return; + // check if has free queue slots + if(!_player->HasFreeBattleGroundQueueId()) + return; + } + else + { + grp = _player->GetGroup(); + // no group found, error + if(!grp) + return; + uint32 err = grp->CanJoinBattleGroundQueue(bgTypeId, bgQueueTypeId, arenatype, arenatype, (bool)isRated, type); + if (err != BG_JOIN_ERR_OK) + { + SendBattleGroundOrArenaJoinError(err); + return; + } + } + + uint32 ateamId = 0; + + if(isRated) + { + ateamId = _player->GetArenaTeamId(type); + // check real arenateam existence only here (if it was moved to group->CanJoin .. () then we would ahve to get it twice) + ArenaTeam * at = objmgr.GetArenaTeamById(ateamId); + if(!at) + { + _player->GetSession()->SendNotInArenaTeamPacket(arenatype); + return; + } + // get the team rating for queueing + arenaRating = at->GetRating(); + // the arenateam id must match for everyone in the group + // get the personal ratings for queueing + uint32 avg_pers_rating = 0; + for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + + // calc avg personal rating + avg_pers_rating += member->GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (type*6) + 5); + } + + if( arenatype ) + avg_pers_rating /= arenatype; + + // if avg personal rating is more than 150 points below the teams rating, the team will be queued against an opponent matching or similar to the average personal rating + if(avg_pers_rating + 150 < arenaRating) + arenaRating = avg_pers_rating; + } + + if(asGroup) + { + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating, ateamId); + sLog.outDebug("Battleground: arena join as group start"); + if(isRated) + sLog.outDebug("Battleground: arena team id %u, leader %s queued with rating %u for type %u",_player->GetArenaTeamId(type),_player->GetName(),arenaRating,arenatype); for(GroupReference *itr = grp->GetFirstMember(); itr != NULL; itr = itr->next()) { Player *member = itr->getSource(); if(!member) continue; - /*if (!member->CanJoinToBattleground()) - //player has deserter aura .. do nothing - */ - - if (member->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA)) - //player is already in this queue - continue; - - // add to queue - uint32 queueSlot = member->AddBattleGroundQueueId(BATTLEGROUND_AA); - if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) - { - WorldPacket data; - //fill data - //member->GetSession()->SendPacket(data); - continue; - } + uint32 queueSlot = member->AddBattleGroundQueueId(bgQueueTypeId);// add to queue // store entry point coords (same as leader entry point) member->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, member->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); member->GetSession()->SendPacket(&data); - sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, BATTLEGROUND_AA); + sBattleGroundMgr.BuildGroupJoinedBattlegroundPacket(&data, bgTypeId); member->GetSession()->SendPacket(&data); - sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(member, BATTLEGROUND_AA); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(member, ginfo); + sLog.outDebug("Battleground: player joined queue for arena as group bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,member->GetGUIDLow(), member->GetName()); } + sLog.outDebug("Battleground: arena join as group end"); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); } else { - /*if (!member->CanJoinToBattleground()) - //player has deserter aura .. do nothing - */ - - if (_player->InBattleGroundQueueForBattleGroundType(BATTLEGROUND_AA)) - //player is already in this queue - return; - - uint32 queueSlot = _player->AddBattleGroundQueueId(BATTLEGROUND_AA); - if (queueSlot == PLAYER_MAX_BATTLEGROUND_QUEUES) - { - WorldPacket data; - //fill data (player is in 3 queues already) - //SendPacket(data); - return; - } + uint32 queueSlot = _player->AddBattleGroundQueueId(bgQueueTypeId); // store entry point coords _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); WorldPacket data; // send status packet (in queue) - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, _player->GetTeam(), queueSlot, STATUS_WAIT_QUEUE, 0, 0, arenatype, isRated); SendPacket(&data); - sBattleGroundMgr.m_BattleGroundQueues[BATTLEGROUND_AA].AddPlayer(_player, BATTLEGROUND_AA); + GroupQueueInfo * ginfo = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddGroup(_player, bgTypeId, arenatype, isRated, arenaRating); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].AddPlayer(_player, ginfo); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgTypeId, _player->GetBattleGroundQueueIdFromLevel(), arenatype, isRated, arenaRating); + sLog.outDebug("Battleground: player joined queue for arena, skirmish, bg queue type %u bg type %u: GUID %u, NAME %s",bgQueueTypeId,bgTypeId,_player->GetGUIDLow(), _player->GetName()); } } @@ -620,3 +819,41 @@ void WorldSession::HandleBattleGroundReportAFK( WorldPacket & recv_data ) reportedPlayer->ReportedAfkBy(_player); } + +void WorldSession::SendBattleGroundOrArenaJoinError(uint8 err) +{ + WorldPacket data; + int32 msg; + switch (err) + { + case BG_JOIN_ERR_OFFLINE_MEMBER: + msg = LANG_BG_GROUP_OFFLINE_MEMBER; + break; + case BG_JOIN_ERR_GROUP_TOO_MANY: + msg = LANG_BG_GROUP_TOO_LARGE; + break; + case BG_JOIN_ERR_MIXED_FACTION: + msg = LANG_BG_GROUP_MIXED_FACTION; + break; + case BG_JOIN_ERR_MIXED_LEVELS: + msg = LANG_BG_GROUP_MIXED_LEVELS; + break; + case BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE: + msg = LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE; + break; + case BG_JOIN_ERR_GROUP_DESERTER: + msg = LANG_BG_GROUP_MEMBER_DESERTER; + break; + case BG_JOIN_ERR_ALL_QUEUES_USED: + msg = LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS; + break; + case BG_JOIN_ERR_GROUP_NOT_ENOUGH: + case BG_JOIN_ERR_MIXED_ARENATEAM: + default: + return; + break; + } + ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_BG_SYSTEM_NEUTRAL, LANG_UNIVERSAL, NULL, 0, GetMangosString(msg), NULL); + SendPacket(&data); + return; +} diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 9c3350bd1..9d3a5ea5c 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -30,10 +30,13 @@ #include "SharedDefines.h" #include "Policies/SingletonImp.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" INSTANTIATE_SINGLETON_1( BattleGroundMgr ); @@ -44,12 +47,12 @@ INSTANTIATE_SINGLETON_1( BattleGroundMgr ); BattleGroundQueue::BattleGroundQueue() { //queues are empty, we don't have to call clear() - for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) +/* for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) { - m_QueuedPlayers[i].Horde = 0; - m_QueuedPlayers[i].Alliance = 0; + //m_QueuedPlayers[i].Horde = 0; + //m_QueuedPlayers[i].Alliance = 0; //m_QueuedPlayers[i].AverageTime = 0; - } + }*/ } BattleGroundQueue::~BattleGroundQueue() @@ -57,31 +60,188 @@ BattleGroundQueue::~BattleGroundQueue() for (int i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) { m_QueuedPlayers[i].clear(); + for(QueuedGroupsList::iterator itr = m_QueuedGroups[i].begin(); itr!= m_QueuedGroups[i].end(); ++itr) + { + delete (*itr); + } + m_QueuedGroups[i].clear(); } } -void BattleGroundQueue::AddPlayer(Player *plr, uint32 bgTypeId) +// 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) +{ + // clear from prev initialization + clear(); + BattleGroundQueue::QueuedGroupsList::iterator itr, next; + // iterate through the source + for(itr = source->begin(); itr!= source->end(); itr = next) + { + next = itr; + ++next; + if( (*itr)->BgTypeId == BgTypeId && // bg type must match + (*itr)->ArenaType == ArenaType && // arena type must match + (*itr)->IsRated == IsRated && // israted must match + (*itr)->IsInvitedToBGInstanceGUID == 0 && // leave out already invited groups + (*itr)->Team == side && // match side + (*itr)->Players.size() <= MaxPlayers && // the group must fit in the bg + ( !excludeTeam || (*itr)->ArenaTeamId != excludeTeam ) && // if excludeTeam is specified, leave out those arena team ids + ( !IsRated || (*itr)->Players.size() == MaxPlayers ) && // if rated, then pass only if the player count is exact NEEDS TESTING! (but now this should never happen) + ( (*itr)->JoinTime <= DisregardTime // pass if disregard time is greater than join time + || (*itr)->ArenaTeamRating == 0 // pass if no rating info + || ( (*itr)->ArenaTeamRating >= MinRating // pass if matches the rating range + && (*itr)->ArenaTeamRating <= MaxRating ) ) ) + { + // the group matches the conditions + // insert it in order of groupsize, and join time + uint32 size = (*itr)->Players.size(); + uint32 jointime = (*itr)->JoinTime; + bool inserted = false; + + for(std::list::iterator elig_itr = begin(); elig_itr != end(); ++elig_itr) + { + // if the next one's size is smaller, then insert + // also insert if the next one's size is equal, but it joined the queue later + if( ((*elig_itr)->Players.size()Players.size() == size && (*elig_itr)->JoinTime > jointime) ) + { + insert(elig_itr,(*itr)); + inserted = true; + break; + } + } + // if not inserted -> this is the smallest group -> push_back + if(!inserted) + { + push_back((*itr)); + } + } + } +} + +// remove group from eligible groups +// used when building selection pools +void BattleGroundQueue::EligibleGroups::RemoveGroup(GroupQueueInfo * ginfo) +{ + for(std::list::iterator itr = begin(); itr != end(); ++itr) + { + if((*itr)==ginfo) + { + erase(itr); + return; + } + } +} + +// selection pool initialization, used to clean up from prev selection +void BattleGroundQueue::SelectionPool::Init() +{ + SelectedGroups.clear(); + MaxGroup = 0; + PlayerCount = 0; +} + +// get the maximal group from the selection pool +// used when building the pool, and have to remove the largest +GroupQueueInfo * BattleGroundQueue::SelectionPool::GetMaximalGroup() +{ + if(SelectedGroups.empty()) + { + sLog.outError("Getting max group when selection pool is empty, this should never happen."); + MaxGroup = NULL; + return 0; + } + // actually select the max group if it's not set + if(MaxGroup==0 && !SelectedGroups.empty()) + { + uint32 max_size = 0; + for(std::list::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr) + { + if(max_size<(*itr)->Players.size()) + { + MaxGroup =(*itr); + max_size = MaxGroup->Players.size(); + } + } + } + return MaxGroup; +} + +// remove group info from selection pool +// used when building selection pools and have to remove maximal group +void BattleGroundQueue::SelectionPool::RemoveGroup(GroupQueueInfo *ginfo) +{ + // uninitiate max group info if needed + if(MaxGroup == ginfo) + MaxGroup = 0; + // find what to remove + for(std::list::iterator itr = SelectedGroups.begin(); itr != SelectedGroups.end(); ++itr) + { + if((*itr)==ginfo) + { + SelectedGroups.erase(itr); + // decrease selected players count + PlayerCount -= ginfo->Players.size(); + return; + } + } +} + +// add group to selection +// used when building selection pools +void BattleGroundQueue::SelectionPool::AddGroup(GroupQueueInfo * ginfo) +{ + SelectedGroups.push_back(ginfo); + // increase selected players count + PlayerCount+=ginfo->Players.size(); + if(!MaxGroup || ginfo->Players.size() > MaxGroup->Players.size()) + { + // update max group info if needed + MaxGroup = 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) +{ + uint32 queue_id = leader->GetBattleGroundQueueIdFromLevel(); + + // create new ginfo + // cannot use the method like in addplayer, because that could modify an in-queue group's stats + // (e.g. leader leaving queue then joining as individual again) + GroupQueueInfo* ginfo = new GroupQueueInfo; + ginfo->BgTypeId = BgTypeId; + ginfo->ArenaType = ArenaType; + ginfo->ArenaTeamId = arenateamid; + ginfo->IsRated = isRated; + ginfo->IsInvitedToBGInstanceGUID = 0; // maybe this should be modifiable by function arguments to enable selection of running instances? + ginfo->JoinTime = getMSTime(); + ginfo->Team = leader->GetTeam(); + ginfo->ArenaTeamRating = arenaRating; + ginfo->OpponentsTeamRating = 0; //initialize it to 0 + + ginfo->Players.clear(); + + m_QueuedGroups[queue_id].push_back(ginfo); + + // return ginfo, because it is needed to add players to this group info + return ginfo; +} + +void BattleGroundQueue::AddPlayer(Player *plr, GroupQueueInfo *ginfo) { uint32 queue_id = plr->GetBattleGroundQueueIdFromLevel(); //if player isn't in queue, he is added, if already is, then values are overwritten, no memory leak PlayerQueueInfo& info = m_QueuedPlayers[queue_id][plr->GetGUID()]; info.InviteTime = 0; - info.IsInvitedToBGInstanceGUID = 0; info.LastInviteTime = 0; info.LastOnlineTime = getMSTime(); - info.Team = plr->GetTeam(); - - //add player to waiting order queue - m_PlayersSortedByWaitTime[queue_id].push_back(plr->GetGUID()); - - if(plr->GetTeam() == ALLIANCE) - ++m_QueuedPlayers[queue_id].Alliance; - else - ++m_QueuedPlayers[queue_id].Horde; - - Update(bgTypeId, queue_id); + info.GroupInfo = ginfo; + // add the pinfo to ginfo's list + ginfo->Players[plr->GetGUID()] = &info; +/* if( sWorld.getConfig(CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE) ) { BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgTypeId); @@ -111,7 +271,8 @@ void BattleGroundQueue::AddPlayer(Player *plr, uint32 bgTypeId) sWorld.SendWorldText(LANG_BG_QUEUE_ANNOUNCE_WORLD, bgName, q_min_level, q_max_level, qAlliance, (MinPlayers > qAlliance) ? (MinPlayers - qAlliance) : 0, qHorde, (MinPlayers > qHorde) ? (MinPlayers - qHorde) : 0); } - } + + }*/ } void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) @@ -120,11 +281,22 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) uint32 queue_id = 0; QueuedPlayersMap::iterator itr; + GroupQueueInfo * group; + QueuedGroupsList::iterator group_itr; bool IsSet = false; - if(!plr) - { //player is offline, we need to find him somewhere in queues - /// there is something wrong if this code is run, because we have in queue only online players! - sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash"); + if(plr) + { + queue_id = plr->GetBattleGroundQueueIdFromLevel(); + + itr = m_QueuedPlayers[queue_id].find(guid); + if(itr != m_QueuedPlayers[queue_id].end()) + IsSet = true; + } + + if(!IsSet) + { + // either player is offline, or he levelled up to another queue category + // sLog.outError("Battleground: removing offline player from BG queue - this might not happen, but it should not cause crash"); for (uint32 i = 0; i < MAX_BATTLEGROUND_QUEUES; i++) { itr = m_QueuedPlayers[i].find(guid); @@ -136,44 +308,248 @@ void BattleGroundQueue::RemovePlayer(uint64 guid, bool decreaseInvitedCount) } } } - else - { //player is online, we have his level, so we can find exact queue from his level - queue_id = plr->GetBattleGroundQueueIdFromLevel(); - itr = m_QueuedPlayers[queue_id].find(guid); - IsSet = true; + + // couldn't find the player in bg queue, return + if(!IsSet) + { + sLog.outError("Battleground: couldn't find player to remove."); + return; } - //all variables are set, so remove player - //remove player from time queue - m_PlayersSortedByWaitTime[queue_id].remove(guid); + group = itr->second.GroupInfo; - if (IsSet && itr != m_QueuedPlayers[queue_id].end()) + for(group_itr=m_QueuedGroups[queue_id].begin(); group_itr != m_QueuedGroups[queue_id].end(); ++group_itr) { - if (!itr->second.IsInvitedToBGInstanceGUID) + if(group == (GroupQueueInfo*)(*group_itr)) + break; + } + + // variables are set (what about leveling up when in queue????) + // remove player from group + // if only player there, remove group + + // remove player queue info from group queue info + std::map::iterator pitr = group->Players.find(guid); + + if(pitr != group->Players.end()) + group->Players.erase(pitr); + + // check for iterator correctness + if (group_itr != m_QueuedGroups[queue_id].end() && itr != m_QueuedPlayers[queue_id].end()) + { + // used when player left the queue, NOT used when porting to bg + if (decreaseInvitedCount) { - if(itr->second.Team == ALLIANCE) - --m_QueuedPlayers[queue_id].Alliance; - else - --m_QueuedPlayers[queue_id].Horde; - } - else - { - if (decreaseInvitedCount) + // if invited to bg, and should decrease invited count, then do it + if(group->IsInvitedToBGInstanceGUID) { - BattleGround* bg = sBattleGroundMgr.GetBattleGround(itr->second.IsInvitedToBGInstanceGUID); + BattleGround* bg = sBattleGroundMgr.GetBattleGround(group->IsInvitedToBGInstanceGUID); if (bg) - bg->DecreaseInvitedCount(itr->second.Team); + bg->DecreaseInvitedCount(group->Team); + if (bg && !bg->GetPlayersSize() && !bg->GetInvitedCount(ALLIANCE) && !bg->GetInvitedCount(HORDE)) + { + // no more players on battleground, set delete it + bg->SetDeleteThis(); + } + } + // update the join queue, maybe now the player's group fits in a queue! + // not yet implemented (should store bgTypeId in group queue info?) + } + // remove player queue info + m_QueuedPlayers[queue_id].erase(itr); + // remove group queue info if needed + if(group->Players.empty()) + { + m_QueuedGroups[queue_id].erase(group_itr); + delete group; + } + // NEEDS TESTING! + // group wasn't empty, so it wasn't deleted, and player have left a rated queue -> everyone from the group should leave too + // don't remove recursively if already invited to bg! + else if(!group->IsInvitedToBGInstanceGUID && decreaseInvitedCount && group->IsRated) + { + // remove next player, this is recursive + // first send removal information + if(Player *plr2 = objmgr.GetPlayer(group->Players.begin()->first)) + { + BattleGround * bg = sBattleGroundMgr.GetBattleGroundTemplate(group->BgTypeId); + uint32 bgQueueTypeId = sBattleGroundMgr.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; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr2->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + plr2->GetSession()->SendPacket(&data); + } + // then actually delete, this may delete the group as well! + RemovePlayer(group->Players.begin()->first,decreaseInvitedCount); + } + } +} + +bool BattleGroundQueue::InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side) +{ + // set side if needed + if(side) + ginfo->Team = side; + + if(!ginfo->IsInvitedToBGInstanceGUID) + { + // not yet invited + // set invitation + ginfo->IsInvitedToBGInstanceGUID = bg->GetInstanceID(); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + // loop through the players + for(std::map::iterator itr = ginfo->Players.begin(); itr != ginfo->Players.end(); ++itr) + { + // set status + itr->second->InviteTime = getMSTime(); + itr->second->LastInviteTime = getMSTime(); + + // get the player + Player* plr = objmgr.GetPlayer(itr->first); + // if offline, skip him + if(!plr) + continue; + + // invite the player + sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID(),ginfo->Team); + + WorldPacket data; + + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); + + sLog.outDebug("Battleground: invited plr %s (%u) to BG instance %u queueindex %u bgtype %u, I can't help it if they don't press the enter battle button.",plr->GetName(),plr->GetGUIDLow(),bg->GetInstanceID(),queueSlot,bg->GetTypeID()); + + // send status packet + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, side?side:plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); + plr->GetSession()->SendPacket(&data); + } + return true; + } + + return false; +} + +// 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) +{ + 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; + } + + // inititate the groups eligible to create the bg + m_EligibleGroups.Init(&(m_QueuedGroups[queue_id]), bgTypeId, side, MaxPlayers, ArenaType, isRated, MinRating, MaxRating, DisregardTime, excludeTeam); + // init the selected groups (clear) + m_SelectionPools[mode].Init(); + while(!(m_EligibleGroups.empty())) + { + sLog.outDebug("m_EligibleGroups is not empty, continue building selection pool"); + // in decreasing group size, add groups to join if they fit in the MaxPlayersPerTeam players + for(EligibleGroups::iterator itr= m_EligibleGroups.begin(); itr!=m_EligibleGroups.end(); ++itr) + { + // get the maximal not yet checked group + GroupQueueInfo * MaxGroup = (*itr); + // if it fits in the maxplayer size, add it + if( (m_SelectionPools[mode].GetPlayerCount() + MaxGroup->Players.size()) <= MaxPlayers ) + { + m_SelectionPools[mode].AddGroup(MaxGroup); + } + } + if(m_SelectionPools[mode].GetPlayerCount()>=MinPlayers) + { + // the selection pool is set, return + sLog.outDebug("pool build succeeded, return true"); + return true; + } + // if the selection pool's not set, then remove the group with the highest player count, and try again with the rest. + GroupQueueInfo * MaxGroup = m_SelectionPools[mode].GetMaximalGroup(); + m_EligibleGroups.RemoveGroup(MaxGroup); + m_SelectionPools[mode].RemoveGroup(MaxGroup); + } + // failed to build a selection pool matching the given values + return false; +} + +// used to remove the Enter Battle window if the battle has already, but someone still has it +// (this can happen in arenas mainly, since the preparation is shorter than the timer for the bgqueueremove event +void BattleGroundQueue::BGEndedRemoveInvites(BattleGround *bg) +{ + uint32 queue_id = bg->GetQueueType(); + uint32 bgInstanceId = bg->GetInstanceID(); + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + QueuedGroupsList::iterator itr, next; + for(itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); itr = next) + { + // must do this way, because the groupinfo will be deleted when all playerinfos are removed + GroupQueueInfo * ginfo = (*itr); + next = itr; + ++next; + // if group was invited to this bg instance, then remove all references + if(ginfo->IsInvitedToBGInstanceGUID == bgInstanceId) + { + // after removing this much playerinfos, the ginfo will be deleted, so we'll use a for loop + uint32 to_remove = ginfo->Players.size(); + uint32 team = ginfo->Team; + for(int i = 0; i < to_remove; ++i) + { + // always remove the first one in the group + std::map::iterator itr2 = ginfo->Players.begin(); + if(itr2 == ginfo->Players.end()) + { + sLog.outError("Empty Players in ginfo, this should never happen!"); + return; + } + + // get the player + Player * plr = objmgr.GetPlayer(itr2->first); + if(!plr) + { + sLog.outError("Player offline when trying to remove from GroupQueueInfo, this should never happen."); + continue; + } + + // get the queueslot + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); + if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue + { + plr->RemoveBattleGroundQueueId(bgQueueTypeId); + // remove player from queue, this might delete the ginfo as well! don't use that pointer after this! + RemovePlayer(itr2->first, true); + // this is probably unneeded, since this player was already invited -> does not fit when initing eligible groups + // but updateing the queue can't hurt + Update(bgQueueTypeId, bg->GetQueueType()); + // send info to client + WorldPacket data; + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, team, queueSlot, STATUS_NONE, 0, 0); + plr->GetSession()->SendPacket(&data); + } } } - m_QueuedPlayers[queue_id].erase(itr); } } /* -this method is called when player is inserted, or removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue -add method calls this by itself, the remove method could works in other way, so you have to call this method from other code after calling remove method +this method is called when group is inserted, or player / group is removed from BG Queue - there is only one player's status changed, so we don't use while(true) cycles to invite whole queue +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) +void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype, bool isRated, uint32 arenaRating) { if (queue_id >= MAX_BATTLEGROUND_QUEUES) { @@ -183,158 +559,352 @@ void BattleGroundQueue::Update(uint32 bgTypeId, uint32 queue_id) } //if no players in queue ... do nothing - if (m_QueuedPlayers[queue_id].Alliance == 0 && m_QueuedPlayers[queue_id].Horde == 0) + if (m_QueuedGroups[queue_id].empty()) return; + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bgTypeId, arenatype); + //battleground with free slot for player should be always the last in this queue - for (BGFreeSlotQueueType::iterator itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); ++itr) + BGFreeSlotQueueType::iterator itr, next; + for (itr = sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].begin(); itr != sBattleGroundMgr.BGFreeSlotQueue[bgTypeId].end(); itr = next) { + next = itr; + ++next; // battleground is running, so if: // DO NOT allow queue manager to invite new player to running arena - if ((*itr)->isBattleGround() && (*itr)->GetQueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE) + if ((*itr)->isBattleGround() && (*itr)->GetTypeID() == bgTypeId && (*itr)->GetQueueType() == queue_id && (*itr)->GetStatus() > STATUS_WAIT_QUEUE && (*itr)->GetStatus() < STATUS_WAIT_LEAVE) { //we must check both teams BattleGround* bg = *itr; //we have to store battleground pointer here, because when battleground is full, it is removed from free queue (not yet implemented!!) // and iterator is invalid - //check if there are some players in queue - if (m_QueuedPlayers[queue_id].Alliance > 0 || m_QueuedPlayers[queue_id].Horde > 0) + for(QueuedGroupsList::iterator itr = m_QueuedGroups[queue_id].begin(); itr != m_QueuedGroups[queue_id].end(); ++itr) { - for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();) + // did the group join for this bg type? + if((*itr)->BgTypeId != bgTypeId) + continue; + // if so, check if fits in + if(bg->GetFreeSlotsForTeam((*itr)->Team) >= (*itr)->Players.size()) { - Player* plr = objmgr.GetPlayer(*itr2); - if (!plr) - { - //something is wrong!, kick player from queue - sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug"); - uint64 oldval = *itr2; - itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); - RemovePlayer(oldval, true); - continue; - } - - // player will be invited, if in bg there is a free slot for him - if (bg->HasFreeSlotsForTeam(plr->GetTeam())) - { - // iterator to player's queue status - QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2); - - // remove him from time queue - itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); - - // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and pls report it) - if (itrPlayerStatus == m_QueuedPlayers[queue_id].end()) - continue; - - // check if player is not already invited - if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID) - { - itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg->GetInstanceID(); - itrPlayerStatus->second.InviteTime = getMSTime(); - itrPlayerStatus->second.LastInviteTime = getMSTime(); - if(itrPlayerStatus->second.Team == ALLIANCE) - --m_QueuedPlayers[queue_id].Alliance; - else - --m_QueuedPlayers[queue_id].Horde; - sBattleGroundMgr.InvitePlayer(plr, bg->GetInstanceID()); - - WorldPacket data; - uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); - plr->GetSession()->SendPacket(&data); - } - } - else - ++itr2; - - //if battleground is FULL, then it is removed from free slot queue - not yet implemented! - if (!bg->HasFreeSlots()) - { - //if bg is full, there is no need to invite other players, so break - break; - //remove BG from BGFreeSlotQueue - not used now, in this system we don't remove BGs from free queue - //bg->RemoveFromBGFreeSlotQueue() --- do not uncomment this - not yet implemented - } + // if group fits in, invite it + InviteGroupToBG((*itr),bg,(*itr)->Team); } } + + if (!bg->HasFreeSlots()) + { + //remove BG from BGFreeSlotQueue + bg->RemoveFromBGFreeSlotQueue(); + } } } - /* THIS IS A CASE THAT IN QUEUE THERE IS ENOUGHT PLAYERS TO START NEW BG */ - //itr->end is the last BG - template, which is not already started! + // finished iterating through the bgs with free slots, maybe we need to create a new bg - /* here will be a most of change, when we create battlegrounds instantiated */ - /* if (there is enough players to start new BG) - Battleground* newbg = sBattleGroundMgr.CreateNewBattleGround(bgTypeId) - - that function will use the COPY constructor on BattleGround class ( in bg manager we should have one battleground as a template - (battleground template will be used only to create new BGs, it will be an instance of BG class, but it won't ever start) */ - - /* following code is working with current Battleground system and it should be removed, when BGs will work like instances */ - BattleGround* bg2 = sBattleGroundMgr.GetBattleGround(bgTypeId); - if (bg2->GetQueueType() != MAX_BATTLEGROUND_QUEUES || bg2->GetStatus() != STATUS_WAIT_QUEUE) - return; - if (m_QueuedPlayers[queue_id].Alliance >= bg2->GetMinPlayersPerTeam() && m_QueuedPlayers[queue_id].Horde >= bg2->GetMinPlayersPerTeam()) + BattleGround * bg_template = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + if(!bg_template) { - bg2->SetStatus(STATUS_WAIT_JOIN); - bg2->SetQueueType(queue_id); + sLog.outError("Battleground: Update: bg template not found for %u", bgTypeId); + return; + } - for (PlayerGuidsSortedByTimeQueue::iterator itr2 = m_PlayersSortedByWaitTime[queue_id].begin(); itr2 != m_PlayersSortedByWaitTime[queue_id].end();) + // get the min. players per team, properly for larger arenas as well. (must have full teams for arena matches!) + uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam(); + uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam(); + if(bg_template->isArena()) + { + if(sBattleGroundMgr.isArenaTesting()) { - Player* plr = objmgr.GetPlayer(*itr2); - if (!plr) + MaxPlayersPerTeam = 1; + MinPlayersPerTeam = 1; + } + else + { + switch(arenatype) { - //something is wrong!, kick player from queue - sLog.outError("BATTLEGROUND: problem with inviting offline player to Battleground queue .... pls report bug"); - uint64 oldval = *itr2; - itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); - RemovePlayer(oldval, true); - continue; + case ARENA_TYPE_2v2: + MaxPlayersPerTeam = 2; + MinPlayersPerTeam = 2; + break; + case ARENA_TYPE_3v3: + MaxPlayersPerTeam = 3; + MinPlayersPerTeam = 3; + break; + case ARENA_TYPE_5v5: + MaxPlayersPerTeam = 5; + MinPlayersPerTeam = 5; + break; + } + } + } + + // found out the minimum and maximum ratings the newly added team should battle against + // arenaRating is the rating of the latest joined team + uint32 arenaMinRating = (arenaRating <= sBattleGroundMgr.GetMaxRatingDifference()) ? 0 : arenaRating - sBattleGroundMgr.GetMaxRatingDifference(); + // if no rating is specified, set maxrating to 0 + uint32 arenaMaxRating = (arenaRating == 0)? 0 : arenaRating + sBattleGroundMgr.GetMaxRatingDifference(); + uint32 discardTime = 0; + // if max rating difference is set and the time past since server startup is greater than the rating discard time + // (after what time the ratings aren't taken into account when making teams) then + // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account + // else leave the discard time on 0, this way all ratings will be discarded + if(sBattleGroundMgr.GetMaxRatingDifference() && getMSTime() >= sBattleGroundMgr.GetRatingDiscardTimer()) + discardTime = getMSTime() - sBattleGroundMgr.GetRatingDiscardTimer(); + + // try to build the selection pools + bool bAllyOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_ALLIANCE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); + if(bAllyOK) + sLog.outDebug("Battleground: ally pool succesfully build"); + else + sLog.outDebug("Battleground: ally pool wasn't created"); + bool bHordeOK = BuildSelectionPool(bgTypeId, queue_id, MinPlayersPerTeam, MaxPlayersPerTeam, NORMAL_HORDE, arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); + if(bHordeOK) + sLog.outDebug("Battleground: horde pool succesfully built"); + else + sLog.outDebug("Battleground: horde pool wasn't created"); + + // if selection pools are ready, create the new bg + if (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}; + uint32 arena_num = urand(0,2); + if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && + !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) && + !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) ) + { + sLog.outError("Battleground: couldn't create any arena instance!"); + return; } - /* TODO: (i'm not sure this code will be useful: - here should be some condition like if (bg2->isArena() && bg2->isRated()) + // set the MaxPlayersPerTeam values based on arenatype + // setting the min player values isn't needed, since we won't be using that value later on. + if(sBattleGroundMgr.isArenaTesting()) { - invite players from 1 certain group on each faction to play arena match - } else if ....and existing code - */ - // player will be invited, if in bg there is a free slot for him - if (bg2->HasFreeSlotsForTeam(plr->GetTeam())) - { - // iterator to player's queue status - QueuedPlayersMap::iterator itrPlayerStatus = m_QueuedPlayers[queue_id].find(*itr2); - - // remove him from time queue - itr2 = m_PlayersSortedByWaitTime[queue_id].erase(itr2); - - // only check to be sure ... but this condition shouldn't be true (if it is true, then there is a bug somewhere and report it) - if (itrPlayerStatus == m_QueuedPlayers[queue_id].end()) - continue; - - //check if player is not already invited - if (!itrPlayerStatus->second.IsInvitedToBGInstanceGUID) - { - itrPlayerStatus->second.IsInvitedToBGInstanceGUID = bg2->GetInstanceID(); - itrPlayerStatus->second.InviteTime = getMSTime(); - itrPlayerStatus->second.LastInviteTime = getMSTime(); - - if(itrPlayerStatus->second.Team == ALLIANCE) - --m_QueuedPlayers[queue_id].Alliance; - else - --m_QueuedPlayers[queue_id].Horde; - - sBattleGroundMgr.InvitePlayer(plr, bg2->GetInstanceID()); - - WorldPacket data; - uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgTypeId); - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg2, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME, 0); - plr->GetSession()->SendPacket(&data); - } + bg2->SetMaxPlayersPerTeam(1); + bg2->SetMaxPlayers(2); } else - ++itr2; + { + switch(arenatype) + { + case ARENA_TYPE_2v2: + bg2->SetMaxPlayersPerTeam(2); + bg2->SetMaxPlayers(4); + break; + case ARENA_TYPE_3v3: + bg2->SetMaxPlayersPerTeam(3); + bg2->SetMaxPlayers(6); + break; + case ARENA_TYPE_5v5: + bg2->SetMaxPlayersPerTeam(5); + bg2->SetMaxPlayers(10); + break; + default: + break; + } + } } + else + { + // create new battleground + bg2 = sBattleGroundMgr.CreateNewBattleGround(bgTypeId); + } + + if(!bg2) + { + sLog.outError("Battleground: couldn't create bg %u",bgTypeId); + return; + } + + // start the joining of the bg + bg2->SetStatus(STATUS_WAIT_JOIN); + bg2->SetQueueType(queue_id); + // initialize arena / rating info + bg2->SetArenaType(arenatype); + // set rating + bg2->SetRated(isRated); + + std::list::iterator itr; + + // invite groups from horde selection pool + for(itr = m_SelectionPools[NORMAL_HORDE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_HORDE].SelectedGroups.end(); ++itr) + { + InviteGroupToBG((*itr),bg2,HORDE); + } + + // invite groups from ally selection pools + for(itr = m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.begin(); itr != m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.end(); ++itr) + { + InviteGroupToBG((*itr),bg2,ALLIANCE); + } + + if (isRated) + { + std::list::iterator itr_alliance = m_SelectionPools[NORMAL_ALLIANCE].SelectedGroups.begin(); + std::list::iterator itr_horde = m_SelectionPools[NORMAL_HORDE].SelectedGroups.begin(); + (*itr_alliance)->OpponentsTeamRating = (*itr_horde)->ArenaTeamRating; + sLog.outDebug("setting oposite teamrating for team %u to %u", (*itr_alliance)->ArenaTeamId, (*itr_alliance)->OpponentsTeamRating); + (*itr_horde)->OpponentsTeamRating = (*itr_alliance)->ArenaTeamRating; + sLog.outDebug("setting oposite teamrating for team %u to %u", (*itr_horde)->ArenaTeamId, (*itr_horde)->OpponentsTeamRating); + } + + // start the battleground bg2->StartBattleGround(); } + + // there weren't enough players for a "normal" match + // if arena, enable horde versus horde or alliance versus alliance teams here + + else if(bg_template->isArena()) + { + bool bOneSideHordeTeam1 = false, bOneSideHordeTeam2 = false; + bool bOneSideAllyTeam1 = false, bOneSideAllyTeam2 = false; + bOneSideHordeTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); + if(bOneSideHordeTeam1) + { + // one team has been selected, find out if other can be selected too + std::list::iterator itr; + // temporarily change the team side to enable building the next pool excluding the already selected groups + for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr) + (*itr)->Team=ALLIANCE; + + bOneSideHordeTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_HORDE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime, (*(m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin()))->ArenaTeamId); + + // change back the team to horde + for(itr = m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_HORDE_TEAM1].SelectedGroups.end(); ++itr) + (*itr)->Team=HORDE; + + if(!bOneSideHordeTeam2) + bOneSideHordeTeam1 = false; + } + if(!bOneSideHordeTeam1) + { + // check for one sided ally + bOneSideAllyTeam1 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM1,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime); + if(bOneSideAllyTeam1) + { + // one team has been selected, find out if other can be selected too + std::list::iterator itr; + // temporarily change the team side to enable building the next pool excluding the already selected groups + for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr) + (*itr)->Team=HORDE; + + bOneSideAllyTeam2 = BuildSelectionPool(bgTypeId, queue_id,MaxPlayersPerTeam,MaxPlayersPerTeam,ONESIDE_ALLIANCE_TEAM2,arenatype, isRated, arenaMinRating, arenaMaxRating, discardTime,(*(m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin()))->ArenaTeamId); + + // change back the team to ally + for(itr = m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.begin(); itr != m_SelectionPools[ONESIDE_ALLIANCE_TEAM1].SelectedGroups.end(); ++itr) + (*itr)->Team=ALLIANCE; + } + + if(!bOneSideAllyTeam2) + bOneSideAllyTeam1 = false; + } + // 1-sided BuildSelectionPool() will work, because the MinPlayersPerTeam == MaxPlayersPerTeam in every arena!!!! + if( (bOneSideHordeTeam1 && bOneSideHordeTeam2) || + (bOneSideAllyTeam1 && bOneSideAllyTeam2) ) + { + // which side has enough players? + uint32 side = 0; + SelectionPoolBuildMode mode1, mode2; + // find out what pools are we using + if(bOneSideAllyTeam1 && bOneSideAllyTeam2) + { + side = ALLIANCE; + mode1 = ONESIDE_ALLIANCE_TEAM1; + mode2 = ONESIDE_ALLIANCE_TEAM2; + } + else + { + side = HORDE; + mode1 = ONESIDE_HORDE_TEAM1; + mode2 = ONESIDE_HORDE_TEAM2; + } + + // create random arena + uint8 arenas[] = {BATTLEGROUND_NA, BATTLEGROUND_BE, BATTLEGROUND_RL}; + uint32 arena_num = urand(0,2); + BattleGround* bg2 = NULL; + if( !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[arena_num%3])) && + !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+1)%3])) && + !(bg2 = sBattleGroundMgr.CreateNewBattleGround(arenas[(arena_num+2)%3])) ) + { + sLog.outError("Could not create arena."); + return; + } + + sLog.outDebug("Battleground: One-faction arena created."); + // init stats + if(sBattleGroundMgr.isArenaTesting()) + { + bg2->SetMaxPlayersPerTeam(1); + bg2->SetMaxPlayers(2); + } + else + { + switch(arenatype) + { + case ARENA_TYPE_2v2: + bg2->SetMaxPlayersPerTeam(2); + bg2->SetMaxPlayers(4); + break; + case ARENA_TYPE_3v3: + bg2->SetMaxPlayersPerTeam(3); + bg2->SetMaxPlayers(6); + break; + case ARENA_TYPE_5v5: + bg2->SetMaxPlayersPerTeam(5); + bg2->SetMaxPlayers(10); + break; + default: + break; + } + } + + bg2->SetRated(isRated); + + // assigned team of the other group + uint32 other_side; + if(side == ALLIANCE) + other_side = HORDE; + else + other_side = ALLIANCE; + + // start the joining of the bg + bg2->SetStatus(STATUS_WAIT_JOIN); + bg2->SetQueueType(queue_id); + // initialize arena / rating info + bg2->SetArenaType(arenatype); + + std::list::iterator itr; + + // invite players from the first group as horde players (actually green team) + for(itr = m_SelectionPools[mode1].SelectedGroups.begin(); itr != m_SelectionPools[mode1].SelectedGroups.end(); ++itr) + { + InviteGroupToBG((*itr),bg2,HORDE); + } + + // invite players from the second group as ally players (actually gold team) + for(itr = m_SelectionPools[mode2].SelectedGroups.begin(); itr != m_SelectionPools[mode2].SelectedGroups.end(); ++itr) + { + InviteGroupToBG((*itr),bg2,ALLIANCE); + } + + if (isRated) + { + std::list::iterator itr_alliance = m_SelectionPools[mode1].SelectedGroups.begin(); + std::list::iterator itr_horde = m_SelectionPools[mode2].SelectedGroups.begin(); + (*itr_alliance)->OpponentsTeamRating = (*itr_horde)->ArenaTeamRating; + (*itr_horde)->OpponentsTeamRating = (*itr_alliance)->ArenaTeamRating; + } + + bg2->StartBattleGround(); + } + } } /*********************************************************/ @@ -361,14 +931,19 @@ bool BGQueueInviteEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); 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[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; - BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); - if (qItr != qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID) + uint32 bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(bg->GetTypeID(), bg->GetArenaType()); + uint32 queueSlot = plr->GetBattleGroundQueueIndex(bgQueueTypeId); + if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue { - WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_WAIT_JOIN, INVITE_ACCEPT_WAIT_TIME/2, 0); - plr->GetSession()->SendPacket(&data); + // 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); + } } } return true; //event will be deleted @@ -387,32 +962,40 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) // player logged off (we should do nothing, he is correctly removed from queue in another procedure) return true; - // Player can be in another BG queue and must be removed in normal way in any case - //if (plr->InBattleGround()) - // // player is already in battleground ... do nothing (battleground queue status is deleted when player is teleported to BG) - // return true; - BattleGround* bg = sBattleGroundMgr.GetBattleGround(m_BgInstanceGUID); if (!bg) return true; - uint32 queueSlot = plr->GetBattleGroundQueueIndex(bg->GetTypeID()); - if (queueSlot < PLAYER_MAX_BATTLEGROUND_QUEUES) // player is in queue (base at player data + 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 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[bg->GetTypeID()].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()]; - BattleGroundQueue::QueuedPlayersMap::const_iterator qItr = qpMap.find(m_PlayerGuid); - if (qItr!=qpMap.end() && qItr->second.IsInvitedToBGInstanceGUID == m_BgInstanceGUID) + BattleGroundQueue::QueuedPlayersMap::iterator qMapItr = sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()].find(m_PlayerGuid); + if (qMapItr != sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].m_QueuedPlayers[plr->GetBattleGroundQueueIdFromLevel()].end() && qMapItr->second.GroupInfo && qMapItr->second.GroupInfo->IsInvitedToBGInstanceGUID == m_BgInstanceGUID) { - plr->RemoveBattleGroundQueueId(bg->GetTypeID()); - sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].RemovePlayer(m_PlayerGuid, true); - sBattleGroundMgr.m_BattleGroundQueues[bg->GetTypeID()].Update(bg->GetTypeID(), bg->GetQueueType()); - + if (qMapItr->second.GroupInfo->IsRated) + { + ArenaTeam * at = objmgr.GetArenaTeamById(qMapItr->second.GroupInfo->ArenaTeamId); + if (at) + { + sLog.outDebug("UPDATING memberLost's personal arena rating for %u by opponents rating: %u", GUID_LOPART(plr->GetGUID()), qMapItr->second.GroupInfo->OpponentsTeamRating); + at->MemberLost(plr, qMapItr->second.GroupInfo->OpponentsTeamRating); + at->SaveToDB(); + } + } + plr->RemoveBattleGroundQueueId(bgQueueTypeId); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].RemovePlayer(m_PlayerGuid, true); + sBattleGroundMgr.m_BattleGroundQueues[bgQueueTypeId].Update(bgQueueTypeId, bg->GetQueueType()); WorldPacket data; - sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, plr->GetTeam(), queueSlot, STATUS_NONE, 0, 0); + sBattleGroundMgr.BuildBattleGroundStatusPacket(&data, bg, m_PlayersTeam, queueSlot, STATUS_NONE, 0, 0); plr->GetSession()->SendPacket(&data); } } + else + sLog.outDebug("Battleground: Player was already removed from queue"); //event will be deleted return true; @@ -431,22 +1014,80 @@ void BGQueueRemoveEvent::Abort(uint64 /*e_time*/) BattleGroundMgr::BattleGroundMgr() { 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; } BattleGroundMgr::~BattleGroundMgr() { - for(std::map::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) - delete itr->second; + BattleGroundSet::iterator itr, next; + for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) + { + next = itr; + ++next; + BattleGround * bg = itr->second; + m_BattleGrounds.erase(itr); + delete bg; + } m_BattleGrounds.clear(); } +// used to update running battlegrounds, and delete finished ones void BattleGroundMgr::Update(time_t diff) { - for(BattleGroundSet::iterator itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); ++itr) + BattleGroundSet::iterator itr, next; + for(itr = m_BattleGrounds.begin(); itr != m_BattleGrounds.end(); itr = next) + { + next = itr; + ++next; itr->second->Update(diff); + // use the SetDeleteThis variable + // direct deletion caused crashes + if(itr->second->m_SetDeleteThis) + { + BattleGround * bg = itr->second; + m_BattleGrounds.erase(itr); + delete bg; + } + } + // if rating difference counts, maybe force-update queues + if(m_MaxRatingDifference) + { + // it's time to force update + if(m_NextRatingDiscardUpdate < diff) + { + // forced update for level 70 rated arenas + 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; + } + else + m_NextRatingDiscardUpdate -= diff; + } + if(m_AutoDistributePoints) + { + if(m_AutoDistributionTimeChecker < diff) + { + if(sWorld.GetGameTime() > m_NextAutoDistributionTime) + { + DistributeArenaPoints(); + m_NextAutoDistributionTime = sWorld.GetGameTime() + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS); + CharacterDatabase.PExecute("UPDATE saved_variables SET NextArenaPointDistributionTime = '"I64FMTD"'", m_NextAutoDistributionTime); + } + m_AutoDistributionTimeChecker = 600000; // check 10 minutes + } + else + m_AutoDistributionTimeChecker -= diff; + } } -void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2) +void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGround *bg, uint32 team, uint8 QueueSlot, uint8 StatusID, uint32 Time1, uint32 Time2, uint32 arenatype, uint8 israted) { // we can be in 3 queues in same time... if(StatusID == 0) @@ -460,10 +1101,55 @@ void BattleGroundMgr::BuildBattleGroundStatusPacket(WorldPacket *data, BattleGro data->Initialize(SMSG_BATTLEFIELD_STATUS, (4+1+1+4+2+4+1+4+4+4)); *data << uint32(QueueSlot); // queue id (0...2) - player can be in 3 queues in time // uint64 in client - *data << uint64( uint64(bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); + *data << uint64( uint64(arenatype ? arenatype : bg->GetArenaType()) | (uint64(0x0D) << 8) | (uint64(bg->GetTypeID()) << 16) | (uint64(0x1F90) << 48) ); *data << uint32(0); // unknown // alliance/horde for BG and skirmish/rated for Arenas - *data << uint8(bg->isArena() ? (bg->isRated() ? 1 : 0) : bg->GetTeamIndexByTeamId(team)); + *data << uint8(bg->isArena() ? ( israted ? israted : bg->isRated() ) : bg->GetTeamIndexByTeamId(team)); +/* *data << uint8(arenatype ? arenatype : bg->GetArenaType()); // team type (0=BG, 2=2x2, 3=3x3, 5=5x5), for arenas // NOT PROPER VALUE IF ARENA ISN'T RUNNING YET!!!! + switch(bg->GetTypeID()) // value depends on bg id + { + case BATTLEGROUND_AV: + *data << uint8(1); + break; + case BATTLEGROUND_WS: + *data << uint8(2); + break; + case BATTLEGROUND_AB: + *data << uint8(3); + break; + case BATTLEGROUND_NA: + *data << uint8(4); + break; + case BATTLEGROUND_BE: + *data << uint8(5); + break; + case BATTLEGROUND_AA: + *data << uint8(6); + break; + case BATTLEGROUND_EY: + *data << uint8(7); + break; + case BATTLEGROUND_RL: + *data << uint8(8); + break; + default: // unknown + *data << uint8(0); + break; + } + + if(bg->isArena() && (StatusID == STATUS_WAIT_QUEUE)) + *data << uint32(BATTLEGROUND_AA); // all arenas I don't think so. + else + *data << uint32(bg->GetTypeID()); // BG id from DBC + + *data << uint16(0x1F90); // unk value 8080 + *data << uint32(bg->GetInstanceID()); // instance id + + if(bg->isBattleGround()) + *data << uint8(bg->GetTeamIndexByTeamId(team)); // team + else + *data << uint8(israted?israted:bg->isRated()); // is rated battle +*/ *data << uint32(StatusID); // status switch(StatusID) { @@ -493,13 +1179,24 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) // last check on 2.4.1 data->Initialize(MSG_PVP_LOG_DATA, (1+1+4+40*bg->GetPlayerScoresSize())); *data << uint8(type); // seems to be type (battleground=0/arena=1) + if(type) // arena { - for(uint8 i = 0; i < 2; i++) + // 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+1+i); // rating change: showed value - 3000 - *data << uint32(0); // 2.4.0, has some to do with rating change... - *data << uint8(0); // some unknown string + *data << uint32(3000-bg->m_ArenaTeamRatingChanges[i]); // rating change: showed value - 3000 + *data << uint32(3999); // huge thanks for TOM_RUS for this! + sLog.outDebug("rating change: %d", bg->m_ArenaTeamRatingChanges[i]); + } + for(int i = 1; i >= 0; --i) + { + uint32 at_id = bg->m_ArenaTeamIds[i]; + ArenaTeam * at = objmgr.GetArenaTeamById(at_id); + if(at) + *data << at->GetName(); + else//*/ + *data << (uint8)0; } } @@ -519,32 +1216,35 @@ void BattleGroundMgr::BuildPvpLogDataPacket(WorldPacket *data, BattleGround *bg) { *data << (uint64)itr->first; *data << (int32)itr->second->KillingBlows; - if(type) + 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; + *data << (int32)itr->second->Deaths; + *data << (int32)(itr->second->BonusHonor); + } + else { - // this value is team (green/gold)? // that part probably wrong - Player *plr = objmgr.GetPlayer(itr->first); if(plr) { - if(plr->GetTeam() == HORDE) + if(team == HORDE) *data << uint8(0); - else if(plr->GetTeam() == ALLIANCE) + else if(team == ALLIANCE) + { *data << uint8(1); + } else *data << uint8(0); } else *data << uint8(0); } - else - { - *data << (int32)itr->second->HonorableKills; - *data << (int32)itr->second->Deaths; - *data << (int32)itr->second->BonusHonor; // bonus honor - } - *data << (int32)itr->second->DamageDone; // damage done - *data << (int32)itr->second->HealingDone; // healing done - switch(bg->GetTypeID()) // battleground specific things + *data << (int32)itr->second->DamageDone; // damage done + *data << (int32)itr->second->HealingDone; // healing done + switch(bg->GetTypeID()) // battleground specific things { case BATTLEGROUND_AV: *data << (uint32)0x00000005; // count of next fields @@ -622,23 +1322,120 @@ void BattleGroundMgr::BuildPlayerJoinedBattleGroundPacket(WorldPacket *data, Pla *data << uint64(plr->GetGUID()); } -void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID) +void BattleGroundMgr::InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team) { // set invited player counters: BattleGround* bg = GetBattleGround(bgInstanceGUID); if(!bg) return; + bg->IncreaseInvitedCount(team); + + plr->SetInviteForBattleGroundQueueType(BGQueueTypeId(bg->GetTypeID(),bg->GetArenaType()), bgInstanceGUID); + + // set the arena teams for rated matches + if(bg->isArena() && bg->isRated()) + { + switch(bg->GetArenaType()) + { + case ARENA_TYPE_2v2: + bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(0)); + break; + case ARENA_TYPE_3v3: + bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(1)); + break; + case ARENA_TYPE_5v5: + bg->SetArenaTeamIdForTeam(team, plr->GetArenaTeamId(2)); + break; + default: + break; + } + } - bg->IncreaseInvitedCount(plr->GetTeam()); - plr->SetInviteForBattleGroundType(bg->GetTypeID()); // create invite events: //add events to player's counters ---- this is not good way - there should be something like global event processor, where we should add those events BGQueueInviteEvent* inviteEvent = new BGQueueInviteEvent(plr->GetGUID(), bgInstanceGUID); plr->m_Events.AddEvent(inviteEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME/2)); - BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, plr->GetTeam()); + BGQueueRemoveEvent* removeEvent = new BGQueueRemoveEvent(plr->GetGUID(), bgInstanceGUID, team); plr->m_Events.AddEvent(removeEvent, plr->m_Events.CalculateTime(INVITE_ACCEPT_WAIT_TIME)); } +BattleGround * BattleGroundMgr::GetBattleGroundTemplate(uint32 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 *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; + } + + // create a copy of the BG template + switch(bgTypeId) + { + case BATTLEGROUND_AV: + bg = new BattleGroundAV(*(BattleGroundAV*)bg_template); + break; + case BATTLEGROUND_WS: + bg = new BattleGroundWS(*(BattleGroundWS*)bg_template); + break; + case BATTLEGROUND_AB: + bg = new BattleGroundAB(*(BattleGroundAB*)bg_template); + break; + case BATTLEGROUND_NA: + bg = new BattleGroundNA(*(BattleGroundNA*)bg_template); + break; + case BATTLEGROUND_BE: + bg = new BattleGroundBE(*(BattleGroundBE*)bg_template); + break; + case BATTLEGROUND_AA: + bg = new BattleGroundAA(*(BattleGroundAA*)bg_template); + break; + case BATTLEGROUND_EY: + bg = new BattleGroundEY(*(BattleGroundEY*)bg_template); + break; + case BATTLEGROUND_RL: + bg = new BattleGroundRL(*(BattleGroundRL*)bg_template); + break; + default: + //bg = new BattleGround; + return 0; + break; // placeholder for non implemented BG + } + + // generate a new instance id + bg->SetInstanceID(MapManager::Instance().GenerateInstanceId()); // set instance id + + // reset the new bg (set status to status_wait_queue from status_none) + bg->Reset(); + + /* will be setup in BG::Update() when the first player is ported in + if(!(bg->SetupBattleGround())) + { + sLog.outError("BattleGround: CreateNewBattleGround: SetupBattleGround failed for bg %u", bgTypeId); + delete bg; + return 0; + } + */ + + // add BG to free slot queue + bg->AddToBGFreeSlotQueue(); + + // add bg to update list + AddBattleGround(bg->GetInstanceID(), bg); + + return bg; +} + +// 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) { // Create the BG @@ -658,12 +1455,8 @@ uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPer } bg->SetMapId(MapID); + bg->Reset(); - if(!bg->SetupBattleGround()) - { - delete bg; - return 0; - } BattlemasterListEntry const *bl = sBattlemasterListStore.LookupEntry(bgTypeId); //in previous method is checked if exists entry in sBattlemasterListStore, so no check needed @@ -673,7 +1466,7 @@ uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPer } bg->SetTypeID(bgTypeId); - bg->SetInstanceID(bgTypeId); // temporary + bg->SetInstanceID(0); // template bg, instance id is 0 bg->SetMinPlayersPerTeam(MinPlayersPerTeam); bg->SetMaxPlayersPerTeam(MaxPlayersPerTeam); bg->SetMinPlayers(MinPlayersPerTeam*2); @@ -682,12 +1475,14 @@ uint32 BattleGroundMgr::CreateBattleGround(uint32 bgTypeId, uint32 MinPlayersPer bg->SetTeamStartLoc(ALLIANCE, Team1StartLocX, Team1StartLocY, Team1StartLocZ, Team1StartLocO); bg->SetTeamStartLoc(HORDE, Team2StartLocX, Team2StartLocY, Team2StartLocZ, Team2StartLocO); bg->SetLevelRange(LevelMin, LevelMax); - //add BaggleGround instance to FreeSlotQueue + + //add BattleGround instance to FreeSlotQueue (.back() will return the template!) bg->AddToBGFreeSlotQueue(); - AddBattleGround(bg->GetInstanceID(), bg); - //sLog.outDetail("BattleGroundMgr: Created new battleground: %u %s (Map %u, %u players per team, Levels %u-%u)", bg_TypeID, bg->m_Name, bg->m_MapId, bg->m_MaxPlayersPerTeam, bg->m_LevelMin, bg->m_LevelMax); - return bg->GetInstanceID(); + // do NOT add to update list, since this is a template battleground! + + // return some not-null value, bgTypeId is good enough for me + return bgTypeId; } void BattleGroundMgr::CreateInitialBattleGrounds() @@ -807,6 +1602,77 @@ void BattleGroundMgr::CreateInitialBattleGrounds() sLog.outString( ">> Loaded %u battlegrounds", count ); } +void BattleGroundMgr::InitAutomaticArenaPointDistribution() +{ + if(m_AutoDistributePoints) + { + sLog.outDebug("Initializing Automatic Arena Point Distribution"); + QueryResult * result = CharacterDatabase.Query("SELECT NextArenaPointDistributionTime FROM saved_variables"); + if(!result) + { + sLog.outDebug("Battleground: Next arena point distribution time not found in SavedVariables, reseting it now."); + m_NextAutoDistributionTime = sWorld.GetGameTime() + BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY * sWorld.getConfig(CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS); + CharacterDatabase.PExecute("INSERT INTO saved_variables (NextArenaPointDistributionTime) VALUES ('"I64FMTD"')", m_NextAutoDistributionTime); + } + else + { + m_NextAutoDistributionTime = (*result)[0].GetUInt64(); + delete result; + } + sLog.outDebug("Automatic Arena Point Distribution initialized."); + } +} + +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.SendGlobalText("Distributing arena points to players...", NULL); + + //temporary structure for storing maximum points to add values for all players + std::map PlayerPoints; + + //at first update all points for all team members + for(ObjectMgr::ArenaTeamMap::iterator team_itr = objmgr.GetArenaTeamMapBegin(); team_itr != objmgr.GetArenaTeamMapEnd(); ++team_itr) + { + if(ArenaTeam * at = team_itr->second) + { + at->UpdateArenaPointsHelper(PlayerPoints); + } + } + + //cycle that gives points to all players + for (std::map::iterator plr_itr = PlayerPoints.begin(); plr_itr != PlayerPoints.end(); ++plr_itr) + { + //update to database + CharacterDatabase.PExecute("UPDATE characters SET arena_pending_points = '%u' WHERE `guid` = '%u'", plr_itr->second, plr_itr->first); + //add points if player is online + Player* pl = objmgr.GetPlayer(plr_itr->first); + if (pl) + pl->ModifyArenaPoints(plr_itr->second); + } + + PlayerPoints.clear(); + + sWorld.SendGlobalText("Finished setting arena points for online players.", NULL); + + sWorld.SendGlobalText("Modifying played count, arena points etc. for loaded arena teams, sending updated stats to online players...", NULL); + for(ObjectMgr::ArenaTeamMap::iterator titr = objmgr.GetArenaTeamMapBegin(); titr != objmgr.GetArenaTeamMapEnd(); ++titr) + { + if(ArenaTeam * at = titr->second) + { + at->FinishWeek(); // set played this week etc values to 0 in memory, too + at->SaveToDB(); // save changes + at->NotifyStatsChanged(); // notify the players of the changes + } + } + + sWorld.SendGlobalText("Modification done.", NULL); + + sWorld.SendGlobalText("Done flushing Arena points.", NULL); +} + void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid, Player* plr, uint32 bgTypeId) { uint32 PlayerLevel = 10; @@ -842,18 +1708,25 @@ void BattleGroundMgr::BuildBattleGroundListPacket(WorldPacket *data, uint64 guid } } -void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 bgTypeId) +void BattleGroundMgr::SendToBattleGround(Player *pl, uint32 instanceId) { - BattleGround *bg = GetBattleGround(bgTypeId); + BattleGround *bg = GetBattleGround(instanceId); if(bg) { uint32 mapid = bg->GetMapId(); float x, y, z, O; - bg->GetTeamStartLoc(pl->GetTeam(), x, y, z, O); + uint32 team = pl->GetBGTeam(); + if(team==0) + team = pl->GetTeam(); + bg->GetTeamStartLoc(team, x, y, z, O); sLog.outDetail("BATTLEGROUND: Sending %s to map %u, X %f, Y %f, Z %f, O %f", pl->GetName(), mapid, x, y, z, O); pl->TeleportTo(mapid, x, y, z, O); } + else + { + sLog.outError("player %u trying to port to non-existent bg instance %u",pl->GetGUIDLow(), instanceId); + } } void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround *bg, uint64 guid) @@ -865,3 +1738,100 @@ void BattleGroundMgr::SendAreaSpiritHealerQueryOpcode(Player *pl, BattleGround * data << guid << time_; 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 +{ + return ( bgTypeId == BATTLEGROUND_AA || + bgTypeId == BATTLEGROUND_BE || + bgTypeId == BATTLEGROUND_NA || + bgTypeId == BATTLEGROUND_RL ); +} + +bool BattleGroundMgr::IsBattleGroundType(uint32 bgTypeId) const +{ + return !IsArenaType(bgTypeId); +} + +uint32 BattleGroundMgr::BGQueueTypeId(uint32 bgTypeId, uint8 arenaType) const +{ + 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; + default: + return 0; + } + default: + return 0; + } +} + +uint32 BattleGroundMgr::BGTemplateId(uint32 bgQueueTypeId) const +{ + 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; + } +} + +uint8 BattleGroundMgr::BGArenaType(uint32 bgQueueTypeId) const +{ + 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; + } +} + +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); + else + sWorld.SendGlobalText("Arenas are set to normal playercount.", NULL); +} diff --git a/src/game/BattleGroundMgr.h b/src/game/BattleGroundMgr.h index 193e5f430..bb2a4faaf 100644 --- a/src/game/BattleGroundMgr.h +++ b/src/game/BattleGroundMgr.h @@ -34,51 +34,99 @@ typedef std::deque BGFreeSlotQueueType; #define MAX_BATTLEGROUND_TYPES 9 // each BG type will be in array -struct PlayerQueueInfo +#define MAX_BATTLEGROUND_QUEUE_TYPES 8 + +#define BATTLEGROUND_ARENA_POINT_DISTRIBUTION_DAY 86400 // seconds in a day + +struct GroupQueueInfo; // type predefinition +struct PlayerQueueInfo // stores information for players in queue { uint32 InviteTime; // first invite time uint32 LastInviteTime; // last invite time - uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG uint32 LastOnlineTime; // for tracking and removing offline players from queue after 5 minutes + GroupQueueInfo * GroupInfo; // pointer to the associated groupqueueinfo +}; + +struct GroupQueueInfo // stores information about the group in queue (also used when joined as solo!) +{ + std::map Players; // player queue info map uint32 Team; // Player team (ALLIANCE/HORDE) - bool IsRated; - bool AsGroup; // uint32 GroupId; - uint8 ArenaType; -}; - -struct PlayersCount -{ - uint32 Alliance; - uint32 Horde; -}; - -template class bgqueue: public std::map<_Kty, _Ty> -{ - public: - uint32 Alliance; - uint32 Horde; - //bool Ready; // not used now - //uint32 AverageTime; //not already implemented (it should be average time in queue for last 10 players) + uint32 BgTypeId; // battleground type id + bool IsRated; // rated + uint8 ArenaType; // 2v2, 3v3, 5v5 or 0 when BG + uint32 ArenaTeamId; // team id if rated match + uint32 JoinTime; // time when group was added + uint32 IsInvitedToBGInstanceGUID; // was invited to certain BG + uint32 ArenaTeamRating; // if rated match, inited to the rating of the team + uint32 OpponentsTeamRating; // for rated arena matches }; +class BattleGround; class BattleGroundQueue { public: BattleGroundQueue(); ~BattleGroundQueue(); -/* - uint32 GetType(); - void SetType(uint32 type);*/ - void Update(uint32 bgTypeId, uint32 queue_id); + void Update(uint32 bgTypeId, uint32 queue_id, uint8 arenatype = 0, bool isRated = false, uint32 minRating = 0); - void AddPlayer(Player *plr, uint32 bgTypeId); + GroupQueueInfo * AddGroup(Player * leader, uint32 BgTypeId, uint8 ArenaType, bool isRated, uint32 ArenaRating, uint32 ArenaTeamId = 0); + void AddPlayer(Player *plr, GroupQueueInfo *ginfo); void RemovePlayer(uint64 guid, bool decreaseInvitedCount); + void DecreaseGroupLength(uint32 queueId, uint32 AsGroup); + void BGEndedRemoveInvites(BattleGround * bg); - typedef bgqueue QueuedPlayersMap; + typedef std::map QueuedPlayersMap; QueuedPlayersMap m_QueuedPlayers[MAX_BATTLEGROUND_QUEUES]; - typedef std::list PlayerGuidsSortedByTimeQueue; - PlayerGuidsSortedByTimeQueue m_PlayersSortedByWaitTime[MAX_BATTLEGROUND_QUEUES]; + + typedef std::list QueuedGroupsList; + QueuedGroupsList m_QueuedGroups[MAX_BATTLEGROUND_QUEUES]; + + // class to hold pointers to the groups eligible for a specific selection pool building mode + class EligibleGroups : public std::list + { + 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 RemoveGroup(GroupQueueInfo * ginfo); + }; + + EligibleGroups m_EligibleGroups; + + // class to select and invite groups to bg + class SelectionPool + { + public: + void Init(); + void AddGroup(GroupQueueInfo * group); + GroupQueueInfo * GetMaximalGroup(); + void RemoveGroup(GroupQueueInfo * group); + uint32 GetPlayerCount() const {return PlayerCount;} + public: + std::list SelectedGroups; + private: + uint32 PlayerCount; + GroupQueueInfo * MaxGroup; + }; + + enum SelectionPoolBuildMode + { + NORMAL_ALLIANCE, + NORMAL_HORDE, + ONESIDE_ALLIANCE_TEAM1, + ONESIDE_ALLIANCE_TEAM2, + ONESIDE_HORDE_TEAM1, + ONESIDE_HORDE_TEAM2, + + NUM_SELECTION_POOL_TYPES + }; + + 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); + + private: + + bool InviteGroupToBG(GroupQueueInfo * ginfo, BattleGround * bg, uint32 side); }; /* @@ -96,7 +144,6 @@ class BGQueueInviteEvent : public BasicEvent private: uint64 m_PlayerGuid; uint32 m_BgInstanceGUID; - }; /* @@ -116,7 +163,6 @@ class BGQueueRemoveEvent : public BasicEvent uint32 m_PlayersTeam; }; - class BattleGroundMgr { public: @@ -132,18 +178,18 @@ class BattleGroundMgr void BuildGroupJoinedBattlegroundPacket(WorldPacket *data, uint32 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); + 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); /* Player invitation */ // called from Queue update, or from Addplayer to queue - void InvitePlayer(Player* plr, uint32 bgInstanceGUID); + void InvitePlayer(Player* plr, uint32 bgInstanceGUID, uint32 team); /* Battlegrounds */ BattleGroundSet::iterator GetBattleGroundsBegin() { return m_BattleGrounds.begin(); }; BattleGroundSet::iterator GetBattleGroundsEnd() { return m_BattleGrounds.end(); }; - BattleGround* GetBattleGround(uint8 ID) + BattleGround* GetBattleGround(uint32 ID) { BattleGroundSet::iterator i = m_BattleGrounds.find(ID); if(i != m_BattleGrounds.end()) @@ -152,9 +198,13 @@ class BattleGroundMgr return NULL; }; + BattleGround * GetBattleGroundTemplate(uint32 bgTypeId); + BattleGround * CreateNewBattleGround(uint32 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); inline void AddBattleGround(uint32 ID, BattleGround* BG) { m_BattleGrounds[ID] = BG; }; + void RemoveBattleGround(uint32 instanceID); void CreateInitialBattleGrounds(); @@ -162,16 +212,39 @@ class BattleGroundMgr /* Battleground queues */ //these queues are instantiated when creating BattlegroundMrg - BattleGroundQueue m_BattleGroundQueues[MAX_BATTLEGROUND_TYPES]; // public, because we need to access them in BG handler code + 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); + 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;} + + void InitAutomaticArenaPointDistribution(); + void DistributeArenaPoints(); + uint32 GetPrematureFinishTime() const {return m_PrematureFinishTimer;} + void ToggleArenaTesting(); + const bool isArenaTesting() const { return m_ArenaTesting; } + private: /* 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; }; #define sBattleGroundMgr MaNGOS::Singleton::Instance() diff --git a/src/game/BattleGroundNA.cpp b/src/game/BattleGroundNA.cpp index ac4705f5c..385de1211 100644 --- a/src/game/BattleGroundNA.cpp +++ b/src/game/BattleGroundNA.cpp @@ -47,6 +47,12 @@ void BattleGroundNA::Update(time_t diff) if (!(m_Events & 0x01)) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_4; i++) SpawnBGObject(i, RESPAWN_IMMEDIATELY); @@ -73,6 +79,9 @@ void BattleGroundNA::Update(time_t diff) for(uint32 i = BG_NA_OBJECT_DOOR_1; i <= BG_NA_OBJECT_DOOR_2; i++) DoorOpen(i); + for(uint32 i = BG_NA_OBJECT_BUFF_1; i <= BG_NA_OBJECT_BUFF_2; i++) + SpawnBGObject(i, 60); + SendMessageToAll(LANG_ARENA_BEGUN); SetStatus(STATUS_IN_PROGRESS); SetStartDelayTime(0); @@ -80,6 +89,11 @@ void BattleGroundNA::Update(time_t diff) for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) if(Player *plr = objmgr.GetPlayer(itr->first)) plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); + + if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } } @@ -96,11 +110,23 @@ void BattleGroundNA::AddPlayer(Player *plr) BattleGroundNAScore* sc = new BattleGroundNAScore; m_PlayerScores[plr->GetGUID()] = sc; + + UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); } void BattleGroundNA::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) { + if(GetStatus() == STATUS_WAIT_LEAVE) + return; + UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); + + if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer) @@ -114,17 +140,27 @@ void BattleGroundNA::HandleKillPlayer(Player *player, Player *killer) return; } - BattleGround::HandleKillPlayer(player, killer); + BattleGround::HandleKillPlayer(player,killer); - uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); + UpdateWorldState(0xa0f, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xa10, GetAlivePlayersCountByTeam(HORDE)); - ++m_TeamKills[killer_team_index]; // add kills to killer's team - - if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) + if(!GetAlivePlayersCountByTeam(ALLIANCE)) { // all opponents killed - EndBattleGround(killer->GetTeam()); + EndBattleGround(HORDE); } + else if(!GetAlivePlayersCountByTeam(HORDE)) + { + // all opponents killed + EndBattleGround(ALLIANCE); + } +} + +bool BattleGroundNA::HandlePlayerUnderMap(Player *player) +{ + player->TeleportTo(GetMapId(),4055.504395,2919.660645,13.611241,player->GetOrientation(),false); + return true; } void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger) @@ -149,19 +185,28 @@ void BattleGroundNA::HandleAreaTrigger(Player *Source, uint32 Trigger) // HandleTriggerBuff(buff_guid,Source); } +void BattleGroundNA::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(0xa0f) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7 + data << uint32(0xa10) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8 + data << uint32(0xa11) << uint32(1); // 9 +} + void BattleGroundNA::ResetBGSubclass() { - m_TeamKills[BG_TEAM_ALLIANCE] = 0; - m_TeamKills[BG_TEAM_HORDE] = 0; + } bool BattleGroundNA::SetupBattleGround() { // gates - if( !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854f, 2966.833f, 12.6462f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179f, 2874.97f, 12.39171f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709f, 2981.777f, 10.70117f, -2.648788f, 0, 0, 0.9697962f, -0.2439165f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064f, 2858.438f, 10.23631f, 0.4928045f, 0, 0, 0.2439165f, 0.9697962f, RESPAWN_IMMEDIATELY)) + if( !AddObject(BG_NA_OBJECT_DOOR_1, BG_NA_OBJECT_TYPE_DOOR_1, 4031.854, 2966.833, 12.6462, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_2, BG_NA_OBJECT_TYPE_DOOR_2, 4081.179, 2874.97, 12.39171, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_3, BG_NA_OBJECT_TYPE_DOOR_3, 4023.709, 2981.777, 10.70117, -2.648788, 0, 0, 0.9697962, -0.2439165, RESPAWN_IMMEDIATELY) + || !AddObject(BG_NA_OBJECT_DOOR_4, BG_NA_OBJECT_TYPE_DOOR_4, 4090.064, 2858.438, 10.23631, 0.4928045, 0, 0, 0.2439165, 0.9697962, RESPAWN_IMMEDIATELY) + // buffs + || !AddObject(BG_NA_OBJECT_BUFF_1, BG_NA_OBJECT_TYPE_BUFF_1, 4009.189941, 2895.250000, 13.052700, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) + || !AddObject(BG_NA_OBJECT_BUFF_2, BG_NA_OBJECT_TYPE_BUFF_2, 4103.330078, 2946.350098, 13.051300, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) { sLog.outErrorDb("BatteGroundNA: Failed to spawn some object!"); return false; diff --git a/src/game/BattleGroundNA.h b/src/game/BattleGroundNA.h index 723e5b08e..a44460919 100644 --- a/src/game/BattleGroundNA.h +++ b/src/game/BattleGroundNA.h @@ -26,7 +26,9 @@ enum BattleGroundNAObjectTypes BG_NA_OBJECT_DOOR_2 = 1, BG_NA_OBJECT_DOOR_3 = 2, BG_NA_OBJECT_DOOR_4 = 3, - BG_NA_OBJECT_MAX = 4 + BG_NA_OBJECT_BUFF_1 = 4, + BG_NA_OBJECT_BUFF_2 = 5, + BG_NA_OBJECT_MAX = 6 }; enum BattleGroundNAObjects @@ -34,7 +36,9 @@ enum BattleGroundNAObjects BG_NA_OBJECT_TYPE_DOOR_1 = 183978, BG_NA_OBJECT_TYPE_DOOR_2 = 183980, BG_NA_OBJECT_TYPE_DOOR_3 = 183977, - BG_NA_OBJECT_TYPE_DOOR_4 = 183979 + BG_NA_OBJECT_TYPE_DOOR_4 = 183979, + BG_NA_OBJECT_TYPE_BUFF_1 = 184663, + BG_NA_OBJECT_TYPE_BUFF_2 = 184664 }; class BattleGroundNAScore : public BattleGroundScore @@ -61,9 +65,8 @@ class BattleGroundNA : public BattleGround void HandleAreaTrigger(Player *Source, uint32 Trigger); bool SetupBattleGround(); virtual void ResetBGSubclass(); + virtual void FillInitialWorldStates(WorldPacket &d); void HandleKillPlayer(Player* player, Player *killer); - - private: - uint32 m_TeamKills[2]; // count of kills for each team + bool HandlePlayerUnderMap(Player * plr); }; #endif diff --git a/src/game/BattleGroundRL.cpp b/src/game/BattleGroundRL.cpp index 4be135c70..bf3b5b029 100644 --- a/src/game/BattleGroundRL.cpp +++ b/src/game/BattleGroundRL.cpp @@ -47,6 +47,13 @@ void BattleGroundRL::Update(time_t diff) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } + for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) SpawnBGObject(i, RESPAWN_IMMEDIATELY); @@ -73,6 +80,9 @@ void BattleGroundRL::Update(time_t diff) for(uint32 i = BG_RL_OBJECT_DOOR_1; i <= BG_RL_OBJECT_DOOR_2; i++) DoorOpen(i); + for(uint32 i = BG_RL_OBJECT_BUFF_1; i <= BG_RL_OBJECT_BUFF_2; i++) + SpawnBGObject(i, 60); + SendMessageToAll(LANG_ARENA_BEGUN); SetStatus(STATUS_IN_PROGRESS); SetStartDelayTime(0); @@ -80,6 +90,11 @@ void BattleGroundRL::Update(time_t diff) for(BattleGroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) if(Player *plr = objmgr.GetPlayer(itr->first)) plr->RemoveAurasDueToSpell(SPELL_ARENA_PREPARATION); + + if(!GetPlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetPlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } } @@ -96,11 +111,23 @@ void BattleGroundRL::AddPlayer(Player *plr) BattleGroundRLScore* sc = new BattleGroundRLScore; m_PlayerScores[plr->GetGUID()] = sc; + + UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); } void BattleGroundRL::RemovePlayer(Player* /*plr*/, uint64 /*guid*/) { + if(GetStatus() == STATUS_WAIT_LEAVE) + return; + UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); + + if(!GetAlivePlayersCountByTeam(ALLIANCE) && GetPlayersCountByTeam(HORDE)) + EndBattleGround(HORDE); + else if(GetPlayersCountByTeam(ALLIANCE) && !GetAlivePlayersCountByTeam(HORDE)) + EndBattleGround(ALLIANCE); } void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer) @@ -114,17 +141,27 @@ void BattleGroundRL::HandleKillPlayer(Player *player, Player *killer) return; } - BattleGround::HandleKillPlayer(player, killer); + BattleGround::HandleKillPlayer(player,killer); - uint32 killer_team_index = GetTeamIndexByTeamId(killer->GetTeam()); + UpdateWorldState(0xbb8, GetAlivePlayersCountByTeam(ALLIANCE)); + UpdateWorldState(0xbb9, GetAlivePlayersCountByTeam(HORDE)); - ++m_TeamKills[killer_team_index]; // add kills to killer's team - - if(m_TeamKills[killer_team_index] >= GetPlayersCountByTeam(player->GetTeam())) + if(!GetAlivePlayersCountByTeam(ALLIANCE)) { // all opponents killed - EndBattleGround(killer->GetTeam()); + EndBattleGround(HORDE); } + else if(!GetAlivePlayersCountByTeam(HORDE)) + { + // all opponents killed + EndBattleGround(ALLIANCE); + } +} + +bool BattleGroundRL::HandlePlayerUnderMap(Player *player) +{ + player->TeleportTo(GetMapId(),1285.810547,1667.896851,39.957642,player->GetOrientation(),false); + return true; } void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger) @@ -150,17 +187,26 @@ void BattleGroundRL::HandleAreaTrigger(Player *Source, uint32 Trigger) // HandleTriggerBuff(buff_guid,Source); } +void BattleGroundRL::FillInitialWorldStates(WorldPacket &data) +{ + data << uint32(0xbb8) << uint32(GetAlivePlayersCountByTeam(ALLIANCE)); // 7 + data << uint32(0xbb9) << uint32(GetAlivePlayersCountByTeam(HORDE)); // 8 + data << uint32(0xbba) << uint32(1); // 9 +} + void BattleGroundRL::ResetBGSubclass() { - m_TeamKills[BG_TEAM_ALLIANCE] = 0; - m_TeamKills[BG_TEAM_HORDE] = 0; + } bool BattleGroundRL::SetupBattleGround() { // gates - if( !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561f, 1601.938f, 31.60557f, -1.457349f, 0, 0, -0.6658813f, 0.7460576f, RESPAWN_IMMEDIATELY) - || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648f, 1730.557f, 31.60557f, 1.684245f, 0, 0, 0.7460582f, 0.6658807f, RESPAWN_IMMEDIATELY)) + if( !AddObject(BG_RL_OBJECT_DOOR_1, BG_RL_OBJECT_TYPE_DOOR_1, 1293.561, 1601.938, 31.60557, -1.457349, 0, 0, -0.6658813, 0.7460576, RESPAWN_IMMEDIATELY) + || !AddObject(BG_RL_OBJECT_DOOR_2, BG_RL_OBJECT_TYPE_DOOR_2, 1278.648, 1730.557, 31.60557, 1.684245, 0, 0, 0.7460582, 0.6658807, RESPAWN_IMMEDIATELY) + // buffs + || !AddObject(BG_RL_OBJECT_BUFF_1, BG_RL_OBJECT_TYPE_BUFF_1, 1328.719971, 1632.719971, 36.730400, -1.448624, 0, 0, 0.6626201, -0.7489557, 120) + || !AddObject(BG_RL_OBJECT_BUFF_2, BG_RL_OBJECT_TYPE_BUFF_2, 1243.300049, 1699.170044, 34.872601, -0.06981307, 0, 0, 0.03489945, -0.9993908, 120)) { sLog.outErrorDb("BatteGroundRL: Failed to spawn some object!"); return false; diff --git a/src/game/BattleGroundRL.h b/src/game/BattleGroundRL.h index 0e9a38bca..dd000ce13 100644 --- a/src/game/BattleGroundRL.h +++ b/src/game/BattleGroundRL.h @@ -24,13 +24,17 @@ enum BattleGroundRLObjectTypes { BG_RL_OBJECT_DOOR_1 = 0, BG_RL_OBJECT_DOOR_2 = 1, - BG_RL_OBJECT_MAX = 2 + BG_RL_OBJECT_BUFF_1 = 2, + BG_RL_OBJECT_BUFF_2 = 3, + BG_RL_OBJECT_MAX = 4 }; enum BattleGroundRLObjects { BG_RL_OBJECT_TYPE_DOOR_1 = 185918, - BG_RL_OBJECT_TYPE_DOOR_2 = 185917 + BG_RL_OBJECT_TYPE_DOOR_2 = 185917, + BG_RL_OBJECT_TYPE_BUFF_1 = 184663, + BG_RL_OBJECT_TYPE_BUFF_2 = 184664 }; class BattleGroundRLScore : public BattleGroundScore @@ -57,9 +61,8 @@ class BattleGroundRL : public BattleGround void HandleAreaTrigger(Player *Source, uint32 Trigger); bool SetupBattleGround(); virtual void ResetBGSubclass(); + virtual void FillInitialWorldStates(WorldPacket &d); void HandleKillPlayer(Player* player, Player *killer); - - private: - uint32 m_TeamKills[2]; // count of kills for each team + bool HandlePlayerUnderMap(Player * plr); }; #endif diff --git a/src/game/BattleGroundWS.cpp b/src/game/BattleGroundWS.cpp index 23c90a763..53c67c16f 100644 --- a/src/game/BattleGroundWS.cpp +++ b/src/game/BattleGroundWS.cpp @@ -49,6 +49,16 @@ void BattleGroundWS::Update(time_t diff) { m_Events |= 0x01; + // setup here, only when at least one player has ported to the map + if(!SetupBattleGround()) + { + EndNow(); + return; + } + +// for(uint32 i = WS_SPIRIT_MAIN_ALLIANCE; i <= WS_SPIRIT_MAIN_HORDE; i++) +// SpawnBGCreature(i, RESPAWN_IMMEDIATELY); + for(uint32 i = BG_WS_OBJECT_DOOR_A_1; i <= BG_WS_OBJECT_DOOR_H_4; i++) { SpawnBGObject(i, RESPAWN_IMMEDIATELY); @@ -285,7 +295,32 @@ void BattleGroundWS::EventPlayerCapturedFlag(Player *Source) void BattleGroundWS::EventPlayerDroppedFlag(Player *Source) { - // Drop allowed in any BG state + if(GetStatus() != STATUS_IN_PROGRESS) + { + // if not running, do not cast things at the dropper player (prevent spawning the "dropped" flag), neither send unnecessary messages + // just take off the aura + if(Source->GetTeam() == ALLIANCE) + { + if(!this->IsHordeFlagPickedup()) + return; + if(GetHordeFlagPickerGUID() == Source->GetGUID()) + { + SetHordeFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_WS_SPELL_WARSONG_FLAG); + } + } + else + { + if(!this->IsAllianceFlagPickedup()) + return; + if(GetAllianceFlagPickerGUID() == Source->GetGUID()) + { + SetAllianceFlagPicker(0); + Source->RemoveAurasDueToSpell(BG_WS_SPELL_SILVERWING_FLAG); + } + } + return; + } const char *message = ""; uint8 type = 0; diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index cc93b4369..ecde680d9 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -36,6 +36,7 @@ #include "PlayerDump.h" #include "SocialMgr.h" #include "Util.h" +#include "ArenaTeam.h" #include "Language.h" class LoginQueryHolder : public SqlQueryHolder @@ -59,7 +60,7 @@ 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 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 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)); @@ -79,6 +80,7 @@ bool LoginQueryHolder::Initialize() res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES, "SELECT genitive, dative, accusative, instrumental, prepositional FROM character_declinedname WHERE guid = '%u'",GUID_LOPART(m_guid)); // 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)); return res; } @@ -411,7 +413,7 @@ void WorldSession::HandleCharDeleteOpcode( WorldPacket & recv_data ) } // is arena team captain - if(objmgr.GetArenaTeamByCapitan(guid)) + if(objmgr.GetArenaTeamByCaptain(guid)) { WorldPacket data(SMSG_CHAR_DELETE, 1); data << (uint8)CHAR_DELETE_FAILED_ARENA_CAPTAIN; diff --git a/src/game/Chat.cpp b/src/game/Chat.cpp index 3c21a28ca..64e4cd028 100644 --- a/src/game/Chat.cpp +++ b/src/game/Chat.cpp @@ -197,6 +197,7 @@ ChatCommand * ChatHandler::getCommandTable() { "Mod32Value", SEC_ADMINISTRATOR, false, &ChatHandler::HandleMod32Value, "", NULL }, { "anim", SEC_GAMEMASTER, false, &ChatHandler::HandleAnimCommand, "", NULL }, { "lootrecipient", SEC_GAMEMASTER, false, &ChatHandler::HandleGetLootRecipient, "", NULL }, + { "arena", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDebugArenaCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; @@ -560,6 +561,7 @@ ChatCommand * ChatHandler::getCommandTable() { "cometome", SEC_ADMINISTRATOR, false, &ChatHandler::HandleComeToMeCommand, "", NULL }, { "damage", SEC_ADMINISTRATOR, false, &ChatHandler::HandleDamageCommand, "", NULL }, { "combatstop", SEC_GAMEMASTER, false, &ChatHandler::HandleCombatStopCommand, "", NULL }, + { "flusharenapoints", SEC_ADMINISTRATOR, false, &ChatHandler::HandleFlushArenaPointsCommand, "", NULL }, { "chardelete", SEC_CONSOLE, true, &ChatHandler::HandleCharacterDeleteCommand, "", NULL }, { "sendmessage", SEC_ADMINISTRATOR, true, &ChatHandler::HandleSendMessageCommand, "", NULL }, { "repairitems", SEC_GAMEMASTER, false, &ChatHandler::HandleRepairitemsCommand, "", NULL }, diff --git a/src/game/Chat.h b/src/game/Chat.h index bd66f6877..bacadbb85 100644 --- a/src/game/Chat.h +++ b/src/game/Chat.h @@ -415,6 +415,7 @@ class ChatHandler bool HandleComeToMeCommand(const char *args); bool HandleCombatStopCommand(const char *args); bool HandleSendMessageCommand(const char * args); + bool HandleFlushArenaPointsCommand(const char *args); bool HandleRepairitemsCommand(const char* args); bool HandleWaterwalkCommand(const char* args); @@ -429,6 +430,7 @@ class ChatHandler bool HandleSaveAllCommand(const char* args); bool HandleGetItemState(const char * args); bool HandleGetLootRecipient(const char * args); + bool HandleDebugArenaCommand(const char * args); Player* getSelectedPlayer(); Creature* getSelectedCreature(); diff --git a/src/game/GameEvent.cpp b/src/game/GameEvent.cpp index 5981fd00c..e94d7c1d7 100644 --- a/src/game/GameEvent.cpp +++ b/src/game/GameEvent.cpp @@ -363,7 +363,7 @@ uint32 GameEvent::Update() // return the next e { uint32 nextEventDelay = max_ge_check_delay; // 1 day uint32 calcDelay; - for (uint16 itr = 1; itr < mGameEvent.size(); itr++) + for (uint16 itr = 1; itr < mGameEvent.size(); ++itr) { //sLog.outErrorDb("Checking event %u",itr); if (CheckOneGameEvent(itr)) diff --git a/src/game/Group.cpp b/src/game/Group.cpp index de97b70b3..8279f4c82 100644 --- a/src/game/Group.cpp +++ b/src/game/Group.cpp @@ -1308,6 +1308,54 @@ void Group::UpdateLooterGuid( Creature* creature, bool ifneed ) SendUpdate(); } +uint32 Group::CanJoinBattleGroundQueue(uint32 bgTypeId, uint32 bgQueueType, uint32 MinPlayerCount, uint32 MaxPlayerCount, bool isRated, uint32 arenaSlot) +{ + // check for min / max count + uint32 memberscount = GetMembersCount(); + if(memberscount < MinPlayerCount) + return BG_JOIN_ERR_GROUP_NOT_ENOUGH; + if(memberscount > MaxPlayerCount) + return BG_JOIN_ERR_GROUP_TOO_MANY; + + // get a player as reference, to compare other players' stats to (arena team id, queue id based on level, etc.) + Player * reference = GetFirstMember()->getSource(); + // no reference found, can't join this way + if(!reference) + return BG_JOIN_ERR_OFFLINE_MEMBER; + + uint32 bgQueueId = reference->GetBattleGroundQueueIdFromLevel(); + uint32 arenaTeamId = reference->GetArenaTeamId(arenaSlot); + uint32 team = reference->GetTeam(); + + // check every member of the group to be able to join + for(GroupReference *itr = GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player *member = itr->getSource(); + // offline member? don't let join + if(!member) + return BG_JOIN_ERR_OFFLINE_MEMBER; + // don't allow cross-faction join as group + if(member->GetTeam() != team) + return BG_JOIN_ERR_MIXED_FACTION; + // not in the same battleground level braket, don't let join + if(member->GetBattleGroundQueueIdFromLevel() != bgQueueId) + return BG_JOIN_ERR_MIXED_LEVELS; + // don't let join rated matches if the arena team id doesn't match + if(isRated && member->GetArenaTeamId(arenaSlot) != arenaTeamId) + return BG_JOIN_ERR_MIXED_ARENATEAM; + // don't let join if someone from the group is already in that bg queue + if(member->InBattleGroundQueueForBattleGroundQueueType(bgQueueType)) + return BG_JOIN_ERR_GROUP_MEMBER_ALREADY_IN_QUEUE; + // check for deserter debuff in case not arena queue + if(bgTypeId != BATTLEGROUND_AA && !member->CanJoinToBattleground()) + return BG_JOIN_ERR_GROUP_DESERTER; + // check if member can join any more battleground queues + if(!member->HasFreeBattleGroundQueueId()) + return BG_JOIN_ERR_ALL_QUEUES_USED; + } + return BG_JOIN_ERR_OK; +} + //=================================================== //============== Roll =============================== //=================================================== diff --git a/src/game/Group.h b/src/game/Group.h index a9e6a733f..84e215fc0 100644 --- a/src/game/Group.h +++ b/src/game/Group.h @@ -247,6 +247,7 @@ class MANGOS_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); void ChangeMembersGroup(const uint64 &guid, const uint8 &group); void ChangeMembersGroup(Player *player, const uint8 &group); diff --git a/src/game/Language.h b/src/game/Language.h index ad5a2b43c..c51cf0f3e 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -641,11 +641,30 @@ enum MangosStrings 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, +// LANG_HIS_ARENA_LEVEL_REQ_ERROR = 714, an opcode exists for this LANG_YOUR_BG_LEVEL_REQ_ERROR = 715, - LANG_YOUR_ARENA_TEAM_FULL = 716, - // Room for BG/ARENA 717-799 not used +// LANG_YOUR_ARENA_TEAM_FULL = 716, an opcode exists for this + + LANG_BG_GROUP_TOO_LARGE = 7007, // "Your group is too large for this battleground. Please regroup to join." + LANG_ARENA_GROUP_TOO_LARGE = 7008, // "Your group is too large for this arena. Please regroup to join." + LANG_ARENA_YOUR_TEAM_ONLY = 7009, // "Your group has members not in your arena team. Please regroup to join." + LANG_ARENA_NOT_ENOUGH_PLAYERS = 7010, // "Your group does not have enough players to join this match." + LANG_ARENA_GOLD_WINS = 7011, // "The Gold Team wins!" + LANG_ARENA_GREEN_WINS = 7012, // "The Green Team wins!" + LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 7013, // The battleground will end soon, because there aren't enough players. Get more ppl or win already! + LANG_BG_GROUP_OFFLINE_MEMBER = 7014, // "Your group has an offline member. Please remove him before joining." + LANG_BG_GROUP_MIXED_FACTION = 7015, // "Your group has players from the opposing faction. You can't join the battleground as a group." + LANG_BG_GROUP_MIXED_LEVELS = 7016, // "Your group has players from different battleground brakets. You can't join as group." + LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 7017, // "Someone in your party is already in this battleground queue. (S)he must leave it before joining as group." + LANG_BG_GROUP_MEMBER_DESERTER = 7018, // "Someone in your party is Deserter. You can't join as group." + LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 7019, // "Someone in your party is already in three battleground queues. You cannot join as group." + + LANG_CANNOT_TELE_TO_BG = 7020, // "You cannot teleport to a battleground or arena map." + LANG_CANNOT_SUMMON_TO_BG = 7021, // "You cannot summon players to a battleground or arena map." + LANG_CANNOT_GO_TO_BG_GM = 7022, // "You must be in GM mode to teleport to a player in a battleground." + LANG_CANNOT_GO_TO_BG_FROM_BG = 7023, // "You cannot teleport to a battleground from another battleground. Please leave the current battleground first." // in game strings // = 800, not used diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index c73231635..26d5b15fe 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -351,7 +351,14 @@ bool ChatHandler::HandleNamegoCommand(const char* args) Map* pMap = m_session->GetPlayer()->GetMap(); - if(pMap->Instanceable()) + if(pMap->IsBattleGroundOrArena()) + { + // cannot summon to bg + PSendSysMessage(LANG_CANNOT_SUMMON_TO_BG,chr->GetName()); + SetSentErrorMessage(true); + return false; + } + else if(pMap->IsDungeon()) { Map* cMap = chr->GetMap(); if( cMap->Instanceable() && cMap->GetInstanceId() != pMap->GetInstanceId() ) @@ -435,6 +442,28 @@ bool ChatHandler::HandleGonameCommand(const char* args) Player *chr = objmgr.GetPlayer(name.c_str()); if (chr) { + 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()); + SetSentErrorMessage(true); + return false; + } + // if already in a bg, don't let port to other + else if (_player->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 + _player->SetBattleGroundId(chr->GetBattleGroundId()); + } + else if(cMap->IsDungeon()) Map* cMap = chr->GetMap(); if(cMap->Instanceable()) { diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index fb2c79bce..e77401167 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -47,6 +47,7 @@ #include "Config/ConfigEnv.h" #include "Util.h" #include "ItemEnchantmentMgr.h" +#include "BattleGroundMgr.h" #include "InstanceSaveMgr.h" #include "InstanceData.h" @@ -6479,6 +6480,12 @@ bool ChatHandler::HandleSendMessageCommand(const char* args) return true; } +bool ChatHandler::HandleFlushArenaPointsCommand(const char * /*args*/) +{ + sBattleGroundMgr.DistributeArenaPoints(); + return true; +} + bool ChatHandler::HandleModifyGenderCommand(const char *args) { if(!*args) diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp index 8037e907d..37ce4522a 100644 --- a/src/game/MapInstanced.cpp +++ b/src/game/MapInstanced.cpp @@ -141,7 +141,17 @@ Map* MapInstanced::GetInstance(const WorldObject* obj) uint32 NewInstanceId = 0; // instanceId of the resulting map Player* player = (Player*)obj; - // TODO: battlegrounds and arenas + if(IsBattleGroundOrArena()) + { + // instantiate or find existing bg map for player + // the instance id is set in battlegroundid + NewInstanceId = player->GetBattleGroundId(); + assert(NewInstanceId); + map = _FindMap(NewInstanceId); + if(!map) + map = CreateBattleGround(NewInstanceId); + return map; + } InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty()); InstanceSave *pSave = pBind ? pBind->save : NULL; diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp index 8833b8322..7c9dad5f1 100644 --- a/src/game/MapManager.cpp +++ b/src/game/MapManager.cpp @@ -107,7 +107,7 @@ MapManager::_GetBaseMap(uint32 id) Guard guard(*this); const MapEntry* entry = sMapStore.LookupEntry(id); - if (entry && entry->IsDungeon()) + if (entry && entry->Instanceable()) { m = new MapInstanced(id, i_gridCleanUpDelay); } diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 372818072..849e3a88d 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -130,22 +130,28 @@ void WorldSession::HandleMoveWorldportAckOpcode() _player->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); // battleground state prepare - if(_player->InBattleGround()) + // only add to bg group and object, if the player was invited (else he entered through command) + if(_player->InBattleGround() && _player->IsInvitedForBattleGroundInstance(_player->GetBattleGroundId())) { BattleGround *bg = _player->GetBattleGround(); if(bg) { + bg->AddPlayer(_player); if(bg->GetMapId() == _player->GetMapId()) // we teleported to bg { - if(!bg->GetBgRaid(_player->GetTeam())) // first player joined + // 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(_player->GetTeam(), group); + bg->SetBgRaid(team, group); group->Create(_player->GetGUIDLow(), _player->GetName()); } else // raid already exist { - bg->GetBgRaid(_player->GetTeam())->AddMember(_player->GetGUID(), _player->GetName()); + bg->GetBgRaid(team)->AddMember(_player->GetGUID(), _player->GetName()); } } } @@ -370,20 +376,29 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data ) if(movementInfo.z < -500.0f) { - // NOTE: this is actually called many times while falling - // even after the player has been teleported away - // TODO: discard movement packets after the player is rooted - if(GetPlayer()->isAlive()) + if(GetPlayer()->InBattleGround() + && GetPlayer()->GetBattleGround() + && GetPlayer()->GetBattleGround()->HandlePlayerUnderMap(_player)) { - GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); - // change the death state to CORPSE to prevent the death timer from - // starting in the next player update - GetPlayer()->KillPlayer(); - GetPlayer()->BuildPlayerRepop(); + // do nothing, the handle already did if returned true } + else + { + // NOTE: this is actually called many times while falling + // even after the player has been teleported away + // TODO: discard movement packets after the player is rooted + if(GetPlayer()->isAlive()) + { + GetPlayer()->EnvironmentalDamage(GetPlayer()->GetGUID(),DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth()); + // change the death state to CORPSE to prevent the death timer from + // starting in the next player update + GetPlayer()->KillPlayer(); + GetPlayer()->BuildPlayerRepop(); + } - // cancel the death timer here if started - GetPlayer()->RepopAtGraveyard(); + // cancel the death timer here if started + GetPlayer()->RepopAtGraveyard(); + } } } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 040c3ce35..83b9d7d76 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -137,13 +137,13 @@ ObjectMgr::ObjectMgr() ObjectMgr::~ObjectMgr() { - for( QuestMap::iterator i = mQuestTemplates.begin( ); i != mQuestTemplates.end( ); ++ i ) + for( QuestMap::iterator i = mQuestTemplates.begin( ); i != mQuestTemplates.end( ); ++i ) { delete i->second; } mQuestTemplates.clear( ); - for( GossipTextMap::iterator i = mGossipText.begin( ); i != mGossipText.end( ); ++ i ) + for( GossipTextMap::iterator i = mGossipText.begin( ); i != mGossipText.end( ); ++i ) { delete i->second; } @@ -151,7 +151,7 @@ ObjectMgr::~ObjectMgr() mAreaTriggers.clear(); - for(PetLevelInfoMap::iterator i = petInfo.begin( ); i != petInfo.end( ); ++ i ) + for(PetLevelInfoMap::iterator i = petInfo.begin( ); i != petInfo.end( ); ++i ) { delete[] i->second; } @@ -226,33 +226,43 @@ Guild* ObjectMgr::GetGuildByLeader(const uint64 &guid) const return NULL; } -ArenaTeam* ObjectMgr::GetArenaTeamById(const uint32 ArenaTeamId) const +ArenaTeam* ObjectMgr::GetArenaTeamById(const uint32 arenateamid) const { - for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr) - if ((*itr)->GetId() == ArenaTeamId) - return *itr; + ArenaTeamMap::const_iterator itr = mArenaTeamMap.find(arenateamid); + if (itr != mArenaTeamMap.end()) + return itr->second; return NULL; } ArenaTeam* ObjectMgr::GetArenaTeamByName(const std::string& arenateamname) const { - for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr) - if ((*itr)->GetName() == arenateamname) - return *itr; + for(ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) + if (itr->second->GetName() == arenateamname) + return itr->second; return NULL; } -ArenaTeam* ObjectMgr::GetArenaTeamByCapitan(uint64 const& guid) const +ArenaTeam* ObjectMgr::GetArenaTeamByCaptain(uint64 const& guid) const { - for(ArenaTeamSet::const_iterator itr = mArenaTeamSet.begin(); itr != mArenaTeamSet.end(); ++itr) - if ((*itr)->GetCaptain() == guid) - return *itr; + for(ArenaTeamMap::const_iterator itr = mArenaTeamMap.begin(); itr != mArenaTeamMap.end(); ++itr) + if (itr->second->GetCaptain() == guid) + return itr->second; return NULL; } +void ObjectMgr::AddArenaTeam(ArenaTeam* arenaTeam) +{ + mArenaTeamMap[arenaTeam->GetId()] = arenaTeam; +} + +void ObjectMgr::RemoveArenaTeam(ArenaTeam* arenaTeam) +{ + mArenaTeamMap.erase( arenaTeam->GetId() ); +} + AuctionHouseObject * ObjectMgr::GetAuctionsMap( uint32 location ) { switch ( location ) @@ -4203,7 +4213,7 @@ void ObjectMgr::AddGossipText(GossipText *pGText) GossipText *ObjectMgr::GetGossipText(uint32 Text_ID) { GossipTextMap::const_iterator itr; - for (itr = mGossipText.begin(); itr != mGossipText.end(); itr++) + for (itr = mGossipText.begin(); itr != mGossipText.end(); ++itr) { if(itr->second->Text_ID == Text_ID) return itr->second; diff --git a/src/game/ObjectMgr.h b/src/game/ObjectMgr.h index fa594e055..48371b908 100644 --- a/src/game/ObjectMgr.h +++ b/src/game/ObjectMgr.h @@ -282,11 +282,11 @@ class ObjectMgr typedef std::set< Group * > GroupSet; typedef std::set< Guild * > GuildSet; - typedef std::set< ArenaTeam * > ArenaTeamSet; + + typedef UNORDERED_MAP ArenaTeamMap; typedef UNORDERED_MAP QuestMap; - typedef UNORDERED_MAP AreaTriggerMap; typedef UNORDERED_MAP AreaTriggerScriptMap; @@ -318,11 +318,13 @@ class ObjectMgr void AddGuild(Guild* guild) { mGuildSet.insert( guild ); } void RemoveGuild(Guild* guild) { mGuildSet.erase( guild ); } - ArenaTeam* GetArenaTeamById(const uint32 ArenaTeamId) const; - ArenaTeam* GetArenaTeamByName(const std::string& ArenaTeamName) const; - ArenaTeam* GetArenaTeamByCapitan(uint64 const& guid) const; - void AddArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.insert( arenateam ); } - void RemoveArenaTeam(ArenaTeam* arenateam) { mArenaTeamSet.erase( arenateam ); } + ArenaTeam* GetArenaTeamById(const uint32 arenateamid) const; + ArenaTeam* GetArenaTeamByName(const std::string& arenateamname) const; + ArenaTeam* GetArenaTeamByCaptain(uint64 const& guid) const; + void AddArenaTeam(ArenaTeam* arenaTeam); + void RemoveArenaTeam(ArenaTeam* arenaTeam); + ArenaTeamMap::iterator GetArenaTeamMapBegin() { return mArenaTeamMap.begin(); } + ArenaTeamMap::iterator GetArenaTeamMapEnd() { return mArenaTeamMap.end(); } static CreatureInfo const *GetCreatureTemplate( uint32 id ); CreatureModelInfo const *GetCreatureModelInfo( uint32 modelid ); @@ -801,7 +803,7 @@ class ObjectMgr GroupSet mGroupSet; GuildSet mGuildSet; - ArenaTeamSet mArenaTeamSet; + ArenaTeamMap mArenaTeamMap; ItemMap mItems; ItemMap mAitems; diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index 1064bd23f..857143749 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -115,14 +115,6 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) return; } - for(uint8 i = 0; i < MAX_ARENA_SLOT; i++) - { - if(_player->GetArenaTeamId(i) && (i == (unk10-1))) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); - return; - } - } switch(unk10) { case 1: @@ -144,6 +136,12 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) sLog.outDebug("unknown selection at buy petition: %u", unk10); return; } + + if(_player->GetArenaTeamId(unk10-1)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); + return; + } } if(type == 9) @@ -153,12 +151,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS); return; } - if(objmgr.IsReservedName(name)) - { - SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID); - return; - } - if(!ObjectMgr::IsValidCharterName(name)) + if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) { SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID); return; @@ -171,12 +164,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } - if(objmgr.IsReservedName(name)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID); - return; - } - if(!ObjectMgr::IsValidCharterName(name)) + if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID); return; @@ -216,6 +204,8 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) _player->SendNewItem(charter, 1, true, false); // a petition is invalid, if both the owner and the type matches + // we checked above, if this player is in an arenateam, so this must be + // datacorruption QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type); std::ostringstream ssInvalidPetitionGUIDs; @@ -429,12 +419,7 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS); return; } - if(objmgr.IsReservedName(newname)) - { - SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID); - return; - } - if(!ObjectMgr::IsValidCharterName(newname)) + if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname)) { SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID); return; @@ -447,12 +432,7 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S); return; } - if(objmgr.IsReservedName(newname)) - { - SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID); - return; - } - if(!ObjectMgr::IsValidCharterName(newname)) + if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname)) { SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID); return; @@ -511,7 +491,13 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) // not let enemies sign guild charter if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != objmgr.GetPlayerTeamByGUID(ownerguid)) + { + if(type != 9) + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); + else + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED); return; + } QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); @@ -527,10 +513,42 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) return; } - if(type != 9 && _player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + if(type != 9) { - // player is too low level to join an arena team - SendNotification(LANG_YOUR_ARENA_LEVEL_REQ_ERROR,sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); + if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW); + return; + } + + uint8 slot = ArenaTeam::GetSlotByType(type); + if(slot >= MAX_ARENA_SLOT) + return; + + if(_player->GetArenaTeamId(slot)) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S); + return; + } + + if(_player->GetArenaTeamIdInvited()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); + return; + } + } + else + { + if(_player->GetGuildId()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD); + return; + } + if(_player->GetGuildIdInvited()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD); + return; + } return; } @@ -619,20 +637,63 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) uint8 signs = 0; uint64 petitionguid, plguid; - uint32 petitiontype; + uint32 type; Player *player; - recv_data >> petitiontype; // 2.0.8 - petition type? + recv_data >> type; recv_data >> petitionguid; // petition guid recv_data >> plguid; // player guid - sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", petitiontype, GUID_LOPART(petitionguid), GUID_LOPART(plguid)); + sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid)); player = ObjectAccessor::FindPlayer(plguid); - if(!player || player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow())) - return; - - // not let offer to enemies if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() ) + { + if(type != 9) + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED); + else + SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED); return; + } + + if(type != 9) + { + if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) + { + // player is too low level to join an arena team + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_PLAYER_TO_LOW); + return; + } + + uint8 slot = ArenaTeam::GetSlotByType(type); + if(slot >= MAX_ARENA_SLOT) + return; + + if(player->GetArenaTeamId(slot)) + { + // player is already in an arena team + SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S); + return; + } + + if(player->GetArenaTeamIdInvited()) + { + SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S); + return; + } + } + else + { + if(player->GetGuildId()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD); + return; + } + + if(player->GetGuildIdInvited()) + { + SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD); + return; + } + } QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); if(!result) @@ -811,7 +872,7 @@ void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data) else // or arena team { ArenaTeam* at = new ArenaTeam; - if(!at->create(_player->GetGUID(), type, name)) + if(!at->Create(_player->GetGUID(), type, name)) { sLog.outError("PetitionsHandler: arena team create failed."); delete at; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 60f89f5ce..5a5fd6450 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -346,8 +346,8 @@ Player::Player (WorldSession *session): Unit() m_bgBattleGroundID = 0; for (int j=0; j < PLAYER_MAX_BATTLEGROUND_QUEUES; j++) { - m_bgBattleGroundQueueID[j].bgType = 0; - m_bgBattleGroundQueueID[j].invited = false; + m_bgBattleGroundQueueID[j].bgQueueType = 0; + m_bgBattleGroundQueueID[j].invitedToInstance = 0; } m_bgTeam = 0; @@ -1499,7 +1499,8 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati MapEntry const* mEntry = sMapStore.LookupEntry(mapid); // don't let enter battlegrounds without assigned battleground id (for example through areatrigger)... - if(!InBattleGround() && mEntry->IsBattleGround() && !GetSession()->GetSecurity()) + // don't let gm level > 1 either + if(!InBattleGround() && mEntry->IsBattleGroundOrArena()) return false; // client without expansion support @@ -3489,6 +3490,29 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC guild->DelMember(guid); } + // 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); + } + // 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); if(resultGroup) @@ -7737,19 +7761,34 @@ void Player::SendInitWorldStates() data << uint32(0xa5f) << uint32(0x0); // 35 break; case 3698: // Nagrand Arena - data << uint32(0xa0f) << uint32(0x0); // 7 - data << uint32(0xa10) << uint32(0x0); // 8 - data << uint32(0xa11) << uint32(0x0); // 9 + if (bg && bg->GetTypeID() == BATTLEGROUND_NA) + bg->FillInitialWorldStates(data); + else + { + data << uint32(0xa0f) << uint32(0x0); // 7 + data << uint32(0xa10) << uint32(0x0); // 8 + data << uint32(0xa11) << uint32(0x0); // 9 show + } break; case 3702: // Blade's Edge Arena - data << uint32(0x9f0) << uint32(0x0); // 7 - data << uint32(0x9f1) << uint32(0x0); // 8 - data << uint32(0x9f3) << uint32(0x0); // 9 + if (bg && bg->GetTypeID() == BATTLEGROUND_BE) + bg->FillInitialWorldStates(data); + else + { + data << uint32(0x9f0) << uint32(0x0); // 7 gold + data << uint32(0x9f1) << uint32(0x0); // 8 green + data << uint32(0x9f3) << uint32(0x0); // 9 show + } break; case 3968: // Ruins of Lordaeron - data << uint32(0xbb8) << uint32(0x0); // 7 - data << uint32(0xbb9) << uint32(0x0); // 8 - data << uint32(0xbba) << uint32(0x0); // 9 + if (bg && bg->GetTypeID() == BATTLEGROUND_RL) + bg->FillInitialWorldStates(data); + else + { + data << uint32(0xbb8) << uint32(0x0); // 7 gold + data << uint32(0xbb9) << uint32(0x0); // 8 green + data << uint32(0xbba) << uint32(0x0); // 9 show + } break; case 3703: // Shattrath City break; @@ -13334,6 +13373,36 @@ void Player::_LoadDeclinedNames(QueryResult* result) delete result; } +void Player::_LoadArenaTeamInfo(QueryResult *result) +{ + // arenateamid, played_week, played_season, personal_rating + memset((void*)&m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1], 0, sizeof(uint32)*18); + if (!result) + return; + + do + { + Field *fields = result->Fetch(); + + uint32 arenateamid = fields[0].GetUInt32(); + uint32 played_week = fields[1].GetUInt32(); + uint32 played_season = fields[2].GetUInt32(); + uint32 personal_rating = fields[3].GetUInt32(); + + ArenaTeam* aTeam = objmgr.GetArenaTeamById(arenateamid); + uint8 arenaSlot = aTeam->GetSlot(); + + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3] = arenateamid; // TeamID + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 1] = ((aTeam->GetCaptain() == GetGUID()) ? (uint32)0 : (uint32)1); // Captain 0, member 1 + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 2] = played_week; // Played Week + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 3] = played_season; // Played Season + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 4] = 0; // Unk + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 5] = personal_rating; // Personal Rating + + }while (result->NextRow()); + delete result; +} + bool Player::LoadPositionFromDB(uint32& mapid, float& x,float& y,float& z,float& o, bool& in_flight, uint64 guid) { QueryResult *result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,taxi_path FROM characters WHERE guid = '%u'",GUID_LOPART(guid)); @@ -13405,8 +13474,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 - //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 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 + //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); QueryResult *result = holder->GetResult(PLAYER_LOGIN_QUERY_LOADFROM); if(!result) @@ -13496,6 +13565,14 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadGroup(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGROUP)); + _LoadArenaTeamInfo(holder->GetResult(PLAYER_LOGIN_QUERY_LOADARENAINFO)); + + uint32 arena_currency = GetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY) + fields[33].GetUInt32(); + if (arena_currency > sWorld.getConfig(CONFIG_MAX_ARENA_POINTS)) + arena_currency = sWorld.getConfig(CONFIG_MAX_ARENA_POINTS); + + SetUInt32Value(PLAYER_FIELD_ARENA_CURRENCY, arena_currency); + // check arena teams integrity for(uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot) { @@ -14818,8 +14895,10 @@ void Player::SaveToDB() // first save/honor gain after midnight will also update the player's honor fields UpdateHonorFields(); - // Must saved before enter into BattleGround - if(InBattleGround()) + // 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; @@ -14857,7 +14936,7 @@ 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) VALUES (" + "death_expire_time, taxi_path, arena_pending_points) VALUES (" << GetGUIDLow() << ", " << GetSession()->GetAccountId() << ", '" << sql_name << "', " @@ -14956,7 +15035,7 @@ void Player::SaveToDB() ss << ", '"; ss << m_taxi.SaveTaxiDestinationsToString(); - ss << "' )"; + ss << "', '0' )"; CharacterDatabase.Execute( ss.str().c_str() ); @@ -17619,7 +17698,8 @@ bool Player::InArena() const bool Player::GetBGAccessByLevel(uint32 bgTypeId) const { - BattleGround *bg = sBattleGroundMgr.GetBattleGround(bgTypeId); + // get a template bg instead of running one + BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); if(!bg) return false; @@ -17657,6 +17737,11 @@ uint32 Player::GetBattleGroundQueueIdFromLevel() const return 6; else return level/10 - 1; // 20..29 -> 1, 30-39 -> 2, ... + /* + assert(bgTypeId < MAX_BATTLEGROUND_TYPES); + BattleGround *bg = sBattleGroundMgr.GetBattleGroundTemplate(bgTypeId); + assert(bg); + return (getLevel() - bg->GetMinLevel()) / 10;*/ } float Player::GetReputationPriceDiscount( Creature const* pCreature ) const diff --git a/src/game/Player.h b/src/game/Player.h index 93ec74775..3ecba2780 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -809,9 +809,10 @@ enum PlayerLoginQueryIndex PLAYER_LOGIN_QUERY_LOADSPELLCOOLDOWNS = 15, PLAYER_LOGIN_QUERY_LOADDECLINEDNAMES = 16, PLAYER_LOGIN_QUERY_LOADGUILD = 17, -}; + PLAYER_LOGIN_QUERY_LOADARENAINFO = 18, -#define MAX_PLAYER_LOGIN_QUERY 18 + MAX_PLAYER_LOGIN_QUERY +}; // Player summoning auto-decline time (in secs) #define MAX_PLAYER_SUMMON_DELAY (2*MINUTE) @@ -1517,7 +1518,6 @@ class MANGOS_DLL_SPEC Player : public Unit void SetInArenaTeam(uint32 ArenaTeamId, uint8 slot) { SetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6), ArenaTeamId); - SaveDataFieldToDB(); // needed? } uint32 GetArenaTeamId(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + (slot * 6)); } static uint32 GetArenaTeamIdFromDB(uint64 guid, uint8 slot); @@ -1804,24 +1804,32 @@ class MANGOS_DLL_SPEC Player : public Unit static uint32 GetMaxLevelForBattleGroundQueueId(uint32 queue_id); uint32 GetBattleGroundQueueIdFromLevel() const; - uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgType; } - uint32 GetBattleGroundQueueIndex(uint32 bgType) const + bool InBattleGroundQueue() const { for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) - if (m_bgBattleGroundQueueID[i].bgType == bgType) + if (m_bgBattleGroundQueueID[i].bgQueueType != 0) + return true; + return false; + } + + uint32 GetBattleGroundQueueId(uint32 index) const { return m_bgBattleGroundQueueID[index].bgQueueType; } + uint32 GetBattleGroundQueueIndex(uint32 bgQueueType) const + { + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) return i; return PLAYER_MAX_BATTLEGROUND_QUEUES; } - bool IsInvitedForBattleGroundType(uint32 bgType) const + bool IsInvitedForBattleGroundQueueType(uint32 bgQueueType) const { for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) - if (m_bgBattleGroundQueueID[i].bgType == bgType) - return m_bgBattleGroundQueueID[i].invited; + if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) + return m_bgBattleGroundQueueID[i].invitedToInstance != 0; return PLAYER_MAX_BATTLEGROUND_QUEUES; } - bool InBattleGroundQueueForBattleGroundType(uint32 bgType) const + bool InBattleGroundQueueForBattleGroundQueueType(uint32 bgQueueType) const { - return GetBattleGroundQueueIndex(bgType) < PLAYER_MAX_BATTLEGROUND_QUEUES; + return GetBattleGroundQueueIndex(bgQueueType) < PLAYER_MAX_BATTLEGROUND_QUEUES; } void SetBattleGroundId(uint32 val) { m_bgBattleGroundID = val; } @@ -1829,34 +1837,47 @@ class MANGOS_DLL_SPEC Player : public Unit { for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { - if (m_bgBattleGroundQueueID[i].bgType == 0 || m_bgBattleGroundQueueID[i].bgType == val) + if (m_bgBattleGroundQueueID[i].bgQueueType == 0 || m_bgBattleGroundQueueID[i].bgQueueType == val) { - m_bgBattleGroundQueueID[i].bgType = val; - m_bgBattleGroundQueueID[i].invited = false; + m_bgBattleGroundQueueID[i].bgQueueType = val; + m_bgBattleGroundQueueID[i].invitedToInstance = 0; return i; } } return PLAYER_MAX_BATTLEGROUND_QUEUES; } + bool HasFreeBattleGroundQueueId() + { + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + if (m_bgBattleGroundQueueID[i].bgQueueType == 0) + return true; + return false; + } void RemoveBattleGroundQueueId(uint32 val) { for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) { - if (m_bgBattleGroundQueueID[i].bgType == val) + if (m_bgBattleGroundQueueID[i].bgQueueType == val) { - m_bgBattleGroundQueueID[i].bgType = 0; - m_bgBattleGroundQueueID[i].invited = false; + m_bgBattleGroundQueueID[i].bgQueueType = 0; + m_bgBattleGroundQueueID[i].invitedToInstance = 0; return; } } } - void SetInviteForBattleGroundType(uint32 bgType) + void SetInviteForBattleGroundQueueType(uint32 bgQueueType, uint32 instanceId) { for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) - if (m_bgBattleGroundQueueID[i].bgType == bgType) - m_bgBattleGroundQueueID[i].invited = true; + if (m_bgBattleGroundQueueID[i].bgQueueType == bgQueueType) + m_bgBattleGroundQueueID[i].invitedToInstance = instanceId; + } + bool IsInvitedForBattleGroundInstance(uint32 instanceId) const + { + for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; i++) + if (m_bgBattleGroundQueueID[i].invitedToInstance == instanceId) + return true; + return false; } - uint32 GetBattleGroundEntryPointMap() const { return m_bgEntryPointMap; } float GetBattleGroundEntryPointX() const { return m_bgEntryPointX; } float GetBattleGroundEntryPointY() const { return m_bgEntryPointY; } @@ -2053,8 +2074,8 @@ class MANGOS_DLL_SPEC Player : public Unit */ struct BgBattleGroundQueueID_Rec { - uint32 bgType; - bool invited; + uint32 bgQueueType; + uint32 invitedToInstance; }; BgBattleGroundQueueID_Rec m_bgBattleGroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES]; uint32 m_bgEntryPointMap; @@ -2099,6 +2120,7 @@ class MANGOS_DLL_SPEC Player : public Unit void _LoadFriendList(QueryResult *result); bool _LoadHomeBind(QueryResult *result); void _LoadDeclinedNames(QueryResult *result); + void _LoadArenaTeamInfo(QueryResult *result); /*********************************************************/ /*** SAVE SYSTEM ***/ diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index a9699c70a..a0a93c079 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -2147,7 +2147,8 @@ void Aura::HandleAuraDummy(bool apply, bool Real) return; // final heal - m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); + if(m_target->IsInWorld()) + m_target->CastCustomSpell(m_target,33778,&m_modifier.m_amount,NULL,NULL,true,NULL,this,GetCasterGUID()); } return; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 5634cc249..08ac6ee18 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2649,7 +2649,7 @@ void Spell::DoCreateItem(uint32 i, uint32 itemtype) return; } - if(BattleGround* bg = sBattleGroundMgr.GetBattleGround(bgType)) + if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType)) bg->SendRewardMarkByMail(player,newitemid,no_space); } } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 0809a6404..5925b21c4 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -605,25 +605,6 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa ((Creature*)pVictim)->SetLootRecipient(this); if (health <= damage) { - // battleground things - if(pVictim->GetTypeId() == TYPEID_PLAYER && (((Player*)pVictim)->InBattleGround())) - { - Player *killed = ((Player*)pVictim); - Player *killer = NULL; - if(GetTypeId() == TYPEID_PLAYER) - killer = ((Player*)this); - else if(GetTypeId() == TYPEID_UNIT && ((Creature*)this)->isPet()) - { - Unit *owner = GetOwner(); - if(owner && owner->GetTypeId() == TYPEID_PLAYER) - killer = ((Player*)owner); - } - - if(killer) - if(BattleGround *bg = killed->GetBattleGround()) - bg->HandleKillPlayer(killed, killer); // drop flags and etc - } - DEBUG_LOG("DealDamage: victim just died"); // find player: owner of controlled `this` or `this` itself maybe @@ -762,6 +743,19 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa 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) { @@ -4173,6 +4167,22 @@ void Unit::RemoveAllAuras() } } +void Unit::RemoveArenaAuras(bool onleave) +{ + // in join, remove positive buffs, on end, remove negative + // used to remove positive visible auras in arenas + for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();) + { + if ( !(iter->second->GetSpellProto()->AttributesEx4 & (1<<21)) // don't remove stances, shadowform, pally/hunter auras + && !iter->second->IsPassive() // don't remove passive auras + && (!(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNAFFECTED_BY_INVULNERABILITY) || !(iter->second->GetSpellProto()->Attributes & SPELL_ATTR_UNK8)) // not unaffected by invulnerability auras or not having that unknown flag (that seemed the most probable) + && (iter->second->IsPositive() ^ onleave)) // remove positive buffs on enter, negative buffs on leave + RemoveAura(iter); + else + ++iter; + } +} + void Unit::RemoveAllAurasOnDeath() { // used just after dieing to remove all visible auras diff --git a/src/game/Unit.h b/src/game/Unit.h index 45a31f668..c0c1753b4 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1012,6 +1012,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void RemoveAurasWithDispelType( DispelType type ); void RemoveAllAuras(); + void RemoveArenaAuras(bool onleave = false); void RemoveAllAurasOnDeath(); void DelayAura(uint32 spellId, uint32 effindex, int32 delaytime); diff --git a/src/game/World.cpp b/src/game/World.cpp index e6623a29a..8556758e2 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -891,6 +891,12 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_LISTEN_RANGE_TEXTEMOTE] = sConfig.GetIntDefault("ListenRange.TextEmote", 25); m_configs[CONFIG_LISTEN_RANGE_YELL] = sConfig.GetIntDefault("ListenRange.Yell", 300); + m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault("Arena.MaxRatingDifference", 0); + m_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfig.GetIntDefault("Arena.RatingDiscardTimer",300000); + m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfig.GetBoolDefault("Arena.AutoDistributePoints", false); + m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfig.GetIntDefault("Arena.AutoDistributeInterval", 7); + + m_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfig.GetIntDefault("BattleGround.PrematureFinishTimer", 0); m_configs[CONFIG_INSTANT_LOGOUT] = sConfig.GetIntDefault("InstantLogout", SEC_MODERATOR); m_VisibleUnitGreyDistance = sConfig.GetFloatDefault("Visibility.Distance.Grey.Unit", 1); @@ -1292,6 +1298,7 @@ void World::SetInitialWorldSettings() ///- Initialize Battlegrounds sLog.outString( "Starting BattleGround System" ); sBattleGroundMgr.CreateInitialBattleGrounds(); + sBattleGroundMgr.InitAutomaticArenaPointDistribution(); //Not sure if this can be moved up in the sequence (with static data loading) as it uses MapManager sLog.outString( "Loading Transports..." ); @@ -2169,7 +2176,7 @@ void World::ScriptsProcess() void World::SendGlobalMessage(WorldPacket *packet, WorldSession *self, uint32 team) { SessionMap::iterator itr; - for (itr = m_sessions.begin(); itr != m_sessions.end(); itr++) + for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { if (itr->second && itr->second->GetPlayer() && @@ -2236,11 +2243,29 @@ void World::SendWorldText(int32 string_id, ...) delete data_cache[i][j]; } +/// Send a System Message to all players (except self if mentioned) +void World::SendGlobalText(const char* text, WorldSession *self) +{ + WorldPacket data; + + // need copy to prevent corruption by strtok call in LineFromMessage original string + char* buf = strdup(text); + char* pos = buf; + + while(char* line = ChatHandler::LineFromMessage(pos)) + { + ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL); + SendGlobalMessage(&data, self); + } + + free(buf); +} + /// Send a packet to all players (or players selected team) in the zone (except self if mentioned) void World::SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self, uint32 team) { SessionMap::iterator itr; - for (itr = m_sessions.begin(); itr != m_sessions.end(); itr++) + for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { if (itr->second && itr->second->GetPlayer() && diff --git a/src/game/World.h b/src/game/World.h index d5b313503..db9cbeca4 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -176,6 +176,11 @@ enum WorldConfigs CONFIG_LISTEN_RANGE_SAY, CONFIG_LISTEN_RANGE_TEXTEMOTE, CONFIG_LISTEN_RANGE_YELL, + CONFIG_ARENA_MAX_RATING_DIFFERENCE, + CONFIG_ARENA_RATING_DISCARD_TIMER, + CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS, + CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, + CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, CONFIG_VALUE_COUNT }; @@ -396,6 +401,7 @@ class World void LoadConfigSettings(bool reload = false); void SendWorldText(int32 string_id, ...); + void SendGlobalText(const char* text, WorldSession *self); void SendGlobalMessage(WorldPacket *packet, WorldSession *self = 0, uint32 team = 0); void SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self = 0, uint32 team = 0); void SendZoneText(uint32 zone, const char *text, WorldSession *self = 0, uint32 team = 0); diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index cd3a4e961..7e20ad4d8 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -177,11 +177,12 @@ class MANGOS_DLL_SPEC WorldSession // Guild/Arena Team void SendGuildCommandResult(uint32 typecmd, const std::string& str, uint32 cmdresult); - void SendArenaTeamCommandResult(uint32 unk1, const std::string& str1, const std::string& str2, uint32 unk3); + void SendArenaTeamCommandResult(uint32 team_action, const std::string& team, const std::string& player, uint32 error_id); void BuildArenaTeamEventPacket(WorldPacket *data, uint8 eventid, uint8 str_count, const std::string& str1, const std::string& str2, const std::string& str3); void SendNotInArenaTeamPacket(uint8 type); void SendPetitionShowList( uint64 guid ); void SendSaveGuildEmblem( uint32 msg ); + void SendBattleGroundOrArenaJoinError(uint8 err); // Looking For Group // TRUE values set by client sending CMSG_LFG_SET_AUTOJOIN and CMSG_LFM_CLEAR_AUTOFILL before player login diff --git a/src/game/debugcmds.cpp b/src/game/debugcmds.cpp index 298411fbd..1b77f9ac6 100644 --- a/src/game/debugcmds.cpp +++ b/src/game/debugcmds.cpp @@ -30,6 +30,7 @@ #include "GossipDef.h" #include "Language.h" #include "MapManager.h" +#include "BattleGroundMgr.h" #include #include "ObjectMgr.h" @@ -518,3 +519,9 @@ bool ChatHandler::HandleGetItemState(const char* args) return true; } + +bool ChatHandler::HandleDebugArenaCommand(const char * /*args*/) +{ + sBattleGroundMgr.ToggleArenaTesting(); + return true; +} diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index f57e25d5a..2c6ca9162 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -1074,6 +1074,48 @@ Death.SicknessLevel = 11 Death.CorpseReclaimDelay.PvP = 1 Death.CorpseReclaimDelay.PvE = 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) +# +################################################################################################################### + +Arena.MaxRatingDifference = 0 +Arena.RatingDiscardTimer = 60000 +Arena.AutoDistributePoints = 0 +Arena.AutoDistributeInterval = 7 + +################################################################################################################### +# +# 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 diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index acabe18f5..57af26fd8 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -434,9 +434,10 @@ struct MapEntry // Helpers uint32 Expansion() const { return addon; } - bool Instanceable() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; } - // NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable + + bool IsDungeon() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; } + bool Instanceable() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID || map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; } bool IsRaid() const { return map_type == MAP_RAID; } bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; } bool IsBattleArena() const { return map_type == MAP_ARENA; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 945fa5396..6b759d284 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6909" + #define REVISION_NR "6910" #endif // __REVISION_NR_H__ From ef903e485c62c1383186265857958c9c17262d72 Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 16 Dec 2008 00:32:09 +0100 Subject: [PATCH 191/256] [6911] Fixed typo. Signed-off-by: ApoC --- src/game/ArenaTeam.cpp | 1 - src/shared/revision_nr.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/game/ArenaTeam.cpp b/src/game/ArenaTeam.cpp index b6df34f98..5f1dfdb93 100644 --- a/src/game/ArenaTeam.cpp +++ b/src/game/ArenaTeam.cpp @@ -180,7 +180,6 @@ bool ArenaTeam::LoadArenaTeamFromDB(uint32 ArenaTeamId) CharacterDatabase.PExecute("DELETE FROM arena_team_member WHERE arenateamid = '%u'", ArenaTeamId); CharacterDatabase.PExecute("DELETE FROM arena_team_stats WHERE arenateamid = '%u'", ArenaTeamId); CharacterDatabase.CommitTransaction(); - // return false return false; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 6b759d284..c052f58bf 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6910" + #define REVISION_NR "6911" #endif // __REVISION_NR_H__ From 6bd2bc4125c7bc222e05555d9336bdd79945132f Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 16 Dec 2008 00:45:28 +0100 Subject: [PATCH 192/256] [6912] Removed forgotten define. Signed-off-by: ApoC --- src/game/BattleGround.h | 1 - src/shared/revision_nr.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/game/BattleGround.h b/src/game/BattleGround.h index bff2eb64d..b18217d36 100644 --- a/src/game/BattleGround.h +++ b/src/game/BattleGround.h @@ -18,7 +18,6 @@ #ifndef __BATTLEGROUND_H #define __BATTLEGROUND_H -#define ARENA_PATCH #include "Common.h" #include "WorldPacket.h" diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c052f58bf..0ec0c3ee2 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6911" + #define REVISION_NR "6912" #endif // __REVISION_NR_H__ From 8ffb28a174fc10acdc909297bbbe0abb8cdca2b1 Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 16 Dec 2008 02:03:23 +0100 Subject: [PATCH 193/256] Added missing changes from arena patch. Renumbered texts to be continuous. Signed-off-by: ApoC --- sql/characters.sql | 13 +++++++- sql/mangos.sql | 20 +++++++++++- sql/updates/2008_12_15_01_mangos_arenas.sql | 36 ++++++++++----------- sql/updates/Makefile.am | 4 +++ src/game/Language.h | 34 +++++++++---------- 5 files changed, 70 insertions(+), 37 deletions(-) diff --git a/sql/characters.sql b/sql/characters.sql index f73ca3c78..c5fd2a6bd 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -15,6 +15,15 @@ /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `saved_variables` +-- + +CREATE TABLE `saved_variables` ( + `NextArenaPointDistributionTime` bigint(40) UNSIGNED NOT NULL DEFAULT '0' +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Variable Saves'; + -- -- Table structure for table `character_db_version` -- @@ -73,7 +82,8 @@ CREATE TABLE `arena_team_member` ( `played_week` int(10) unsigned NOT NULL default '0', `wons_week` int(10) unsigned NOT NULL default '0', `played_season` int(10) unsigned NOT NULL default '0', - `wons_season` int(10) unsigned NOT NULL default '0' + `wons_season` int(10) unsigned NOT NULL default '0', + `personal_rating` int(10) UNSIGNED NOT NULL DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- @@ -201,6 +211,7 @@ CREATE TABLE `characters` ( `zone` int(11) unsigned NOT NULL default '0', `death_expire_time` bigint(20) unsigned NOT NULL default '0', `taxi_path` text, + `arena_pending_points` int(10) UNSIGNED NOT NULL default '0', PRIMARY KEY (`guid`), KEY `idx_account` (`account`), KEY `idx_online` (`online`), diff --git a/sql/mangos.sql b/sql/mangos.sql index 7c5817f30..ab1d64f9b 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -251,6 +251,7 @@ INSERT INTO `command` VALUES ('event start',2,'Syntax: .event start #event_id\r\nStart event #event_id. Set start time for event to current moment (change not saved in DB).'), ('event stop',2,'Syntax: .event stop #event_id\r\nStop event #event_id. Set start time for event to time in past that make current moment is event stop time (change not saved in DB).'), ('explorecheat',3,'Syntax: .explorecheat #flag\r\n\r\nReveal or hide all maps for the selected player. If no player is selected, hide or reveal maps to you.\r\n\r\nUse a #flag of value 1 to reveal, use a #flag value of 0 to hide all maps.'), +('flusharenapoints','3','Syntax: .flusharenapoints\r\n\r\nUse it to distribute arena points based on arena team ratings, and start a new week.'), ('gm',1,'Syntax: .gm [on/off]\r\n\r\nEnable or Disable in game GM MODE or show current state of on/off not provided.'), ('gm chat',1,'Syntax: .gm chat [on/off]\r\n\r\nEnable or disable chat GM MODE (show gm badge in messages) or show current state of on/off not provided.'), ('gm fly',3,'Syntax: .gm fly on/off\r\nEnable/disable gm fly mode.'), @@ -2753,7 +2754,24 @@ INSERT INTO `mangos_string` VALUES (1118,'%d - guild: %s (guid: %u) %s',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1119,'You must use male or female as gender.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (1120,'You change gender of %s to %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), -(1121,'Your gender changed to %s by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +(1121,'Your gender changed to %s by %s.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1122,'Your group is too large for this battleground. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1123,'Your group is too large for this arena. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1124,'Your group has members not in your arena team. Please regroup to join.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1125,'Your group does not have enough players to join this match.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1126,'The Gold Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1127,'The Green Team wins!',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1128,'There aren\'t enough players in this battleground. It will end soon unless some more players join to balance the fight.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1129,'Your group has an offline member. Please remove him before joining.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1130,'Your group has players from the opposing faction. You can\'t join the battleground as a group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1131,'Your group has players from different battleground brakets. You can\'t join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1132,'Someone in your party is already in this battleground queue. (S)he must leave it before joining as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1133,'Someone in your party is Deserter. You can\'t join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1134,'Someone in your party is already in three battleground queues. You cannot join as group.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1135,'You cannot teleport to a battleground or arena map.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1136,'You cannot summon players to a battleground or arena map.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1137,'You must be in GM mode to teleport to a player in a battleground.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1138,'You cannot teleport to a battleground from another battleground. Please leave the current battleground first.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); /*!40000 ALTER TABLE `mangos_string` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/2008_12_15_01_mangos_arenas.sql b/sql/updates/2008_12_15_01_mangos_arenas.sql index f57ea8a3f..0278724a5 100644 --- a/sql/updates/2008_12_15_01_mangos_arenas.sql +++ b/sql/updates/2008_12_15_01_mangos_arenas.sql @@ -2,25 +2,25 @@ DELETE FROM `command` WHERE `name` = "flusharenapoints"; INSERT INTO `command` (`name`, `security`, `help`) VALUES ('flusharenapoints','3','Syntax: .flusharenapoints\r\n\r\nUse it to distribute arena points based on arena team ratings, and start a new week.'); -DELETE FROM mangos_string WHERE entry BETWEEN 7007 AND 7023; +DELETE FROM mangos_string WHERE entry BETWEEN 1122 AND 1138; INSERT INTO mangos_string (entry, content_default) VALUES - (7007,'Your group is too large for this battleground. Please regroup to join.'), - (7008,'Your group is too large for this arena. Please regroup to join.'), - (7009,'Your group has members not in your arena team. Please regroup to join.'), - (7010,'Your group does not have enough players to join this match.'), - (7011,'The Gold Team wins!'), - (7012,'The Green Team wins!'), - (7013, 'There aren\'t enough players in this battleground. It will end soon unless some more players join to balance the fight.'), - (7014, 'Your group has an offline member. Please remove him before joining.'), - (7015, 'Your group has players from the opposing faction. You can\'t join the battleground as a group.'), - (7016, 'Your group has players from different battleground brakets. You can\'t join as group.'), - (7017, 'Someone in your party is already in this battleground queue. (S)he must leave it before joining as group.'), - (7018, 'Someone in your party is Deserter. You can\'t join as group.'), - (7019, 'Someone in your party is already in three battleground queues. You cannot join as group.'), - (7020, 'You cannot teleport to a battleground or arena map.'), - (7021, 'You cannot summon players to a battleground or arena map.'), - (7022, 'You must be in GM mode to teleport to a player in a battleground.'), - (7023, 'You cannot teleport to a battleground from another battleground. Please leave the current battleground first.'); + (1122,'Your group is too large for this battleground. Please regroup to join.'), + (1123,'Your group is too large for this arena. Please regroup to join.'), + (1124,'Your group has members not in your arena team. Please regroup to join.'), + (1125,'Your group does not have enough players to join this match.'), + (1126,'The Gold Team wins!'), + (1127,'The Green Team wins!'), + (1128, 'There aren\'t enough players in this battleground. It will end soon unless some more players join to balance the fight.'), + (1129, 'Your group has an offline member. Please remove him before joining.'), + (1130, 'Your group has players from the opposing faction. You can\'t join the battleground as a group.'), + (1131, 'Your group has players from different battleground brakets. You can\'t join as group.'), + (1132, 'Someone in your party is already in this battleground queue. (S)he must leave it before joining as group.'), + (1133, 'Someone in your party is Deserter. You can\'t join as group.'), + (1134, 'Someone in your party is already in three battleground queues. You cannot join as group.'), + (1135, 'You cannot teleport to a battleground or arena map.'), + (1136, 'You cannot summon players to a battleground or arena map.'), + (1127, 'You must be in GM mode to teleport to a player in a battleground.'), + (1138, 'You cannot teleport to a battleground from another battleground. Please leave the current battleground first.'); DELETE FROM mangos_string WHERE entry = 714 OR entry = 716; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index c4ca950f1..6cebe667c 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -141,6 +141,8 @@ pkgdata_DATA = \ 2008_11_29_01_mangos_spell_proc_event.sql \ 2008_11_29_02_mangos_spell_elixir.sql \ 2008_12_03_01_character_guild_member.sql \ + 2008_12_15_01_character_arenas.sql \ + 2008_12_15_01_mangos_arenas.sql \ README ## Additional files to include when running 'make dist' @@ -263,4 +265,6 @@ EXTRA_DIST = \ 2008_11_29_01_mangos_spell_proc_event.sql \ 2008_11_29_02_mangos_spell_elixir.sql \ 2008_12_03_01_character_guild_member.sql \ + 2008_12_15_01_character_arenas.sql \ + 2008_12_15_01_mangos_arenas.sql \ README diff --git a/src/game/Language.h b/src/game/Language.h index c51cf0f3e..b82d2ed3b 100644 --- a/src/game/Language.h +++ b/src/game/Language.h @@ -647,24 +647,24 @@ enum MangosStrings LANG_YOUR_BG_LEVEL_REQ_ERROR = 715, // LANG_YOUR_ARENA_TEAM_FULL = 716, an opcode exists for this - LANG_BG_GROUP_TOO_LARGE = 7007, // "Your group is too large for this battleground. Please regroup to join." - LANG_ARENA_GROUP_TOO_LARGE = 7008, // "Your group is too large for this arena. Please regroup to join." - LANG_ARENA_YOUR_TEAM_ONLY = 7009, // "Your group has members not in your arena team. Please regroup to join." - LANG_ARENA_NOT_ENOUGH_PLAYERS = 7010, // "Your group does not have enough players to join this match." - LANG_ARENA_GOLD_WINS = 7011, // "The Gold Team wins!" - LANG_ARENA_GREEN_WINS = 7012, // "The Green Team wins!" - LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 7013, // The battleground will end soon, because there aren't enough players. Get more ppl or win already! - LANG_BG_GROUP_OFFLINE_MEMBER = 7014, // "Your group has an offline member. Please remove him before joining." - LANG_BG_GROUP_MIXED_FACTION = 7015, // "Your group has players from the opposing faction. You can't join the battleground as a group." - LANG_BG_GROUP_MIXED_LEVELS = 7016, // "Your group has players from different battleground brakets. You can't join as group." - LANG_BG_GROUP_MEMBER_ALREADY_IN_QUEUE = 7017, // "Someone in your party is already in this battleground queue. (S)he must leave it before joining as group." - LANG_BG_GROUP_MEMBER_DESERTER = 7018, // "Someone in your party is Deserter. You can't join as group." - LANG_BG_GROUP_MEMBER_NO_FREE_QUEUE_SLOTS = 7019, // "Someone in your party is already in three battleground queues. You cannot join as group." + 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 = 7020, // "You cannot teleport to a battleground or arena map." - LANG_CANNOT_SUMMON_TO_BG = 7021, // "You cannot summon players to a battleground or arena map." - LANG_CANNOT_GO_TO_BG_GM = 7022, // "You must be in GM mode to teleport to a player in a battleground." - LANG_CANNOT_GO_TO_BG_FROM_BG = 7023, // "You cannot teleport to a battleground from another battleground. Please leave the current battleground first." + 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 // = 800, not used From d34842f7865b07bb57c749335d9822324683441f Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 16 Dec 2008 02:14:48 +0100 Subject: [PATCH 194/256] Typo fix. Signed-off-by: ApoC --- sql/updates/2008_12_15_01_mangos_arenas.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/updates/2008_12_15_01_mangos_arenas.sql b/sql/updates/2008_12_15_01_mangos_arenas.sql index 0278724a5..589aacfb6 100644 --- a/sql/updates/2008_12_15_01_mangos_arenas.sql +++ b/sql/updates/2008_12_15_01_mangos_arenas.sql @@ -20,7 +20,7 @@ INSERT INTO mangos_string (entry, content_default) VALUES (1134, 'Someone in your party is already in three battleground queues. You cannot join as group.'), (1135, 'You cannot teleport to a battleground or arena map.'), (1136, 'You cannot summon players to a battleground or arena map.'), - (1127, 'You must be in GM mode to teleport to a player in a battleground.'), + (1137, 'You must be in GM mode to teleport to a player in a battleground.'), (1138, 'You cannot teleport to a battleground from another battleground. Please leave the current battleground first.'); DELETE FROM mangos_string WHERE entry = 714 OR entry = 716; From d43bd7efe9c2abf4955d2765980caec04fbf5949 Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 16 Dec 2008 02:20:45 +0100 Subject: [PATCH 195/256] Added missing alters to db_version. Signed-off-by: ApoC --- sql/characters.sql | 2 +- sql/mangos.sql | 2 +- sql/updates/2008_12_15_01_character_arenas.sql | 2 ++ sql/updates/2008_12_15_01_mangos_arenas.sql | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sql/characters.sql b/sql/characters.sql index c5fd2a6bd..fc4c3e95a 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -30,7 +30,7 @@ CREATE TABLE `saved_variables` ( DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_2008_12_03_01_character_guild_member` bit(1) default NULL + `required_2008_12_15_01_character_arenas` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- diff --git a/sql/mangos.sql b/sql/mangos.sql index ab1d64f9b..081d18fbd 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_2008_11_29_02_mangos_spell_elixir` bit(1) default NULL + `required_2008_12_15_01_mangos_arenas` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- diff --git a/sql/updates/2008_12_15_01_character_arenas.sql b/sql/updates/2008_12_15_01_character_arenas.sql index 2976d343e..5fdf0870f 100644 --- a/sql/updates/2008_12_15_01_character_arenas.sql +++ b/sql/updates/2008_12_15_01_character_arenas.sql @@ -1,3 +1,5 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_03_01_character_guild_member required_2008_12_15_01_character_arenas bit; + CREATE TABLE `saved_variables` ( `NextArenaPointDistributionTime` bigint(40) UNSIGNED NOT NULL DEFAULT '0' ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Variable Saves'; diff --git a/sql/updates/2008_12_15_01_mangos_arenas.sql b/sql/updates/2008_12_15_01_mangos_arenas.sql index 589aacfb6..c8208b844 100644 --- a/sql/updates/2008_12_15_01_mangos_arenas.sql +++ b/sql/updates/2008_12_15_01_mangos_arenas.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_11_29_02_mangos_spell_elixir required_2008_12_15_01_mangos_arenas bit; + DELETE FROM `command` WHERE `name` = "flusharenapoints"; INSERT INTO `command` (`name`, `security`, `help`) VALUES ('flusharenapoints','3','Syntax: .flusharenapoints\r\n\r\nUse it to distribute arena points based on arena team ratings, and start a new week.'); From 98281cc3898494a58288c35fa8abcabcbbeba76f Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 16 Dec 2008 05:15:39 +0100 Subject: [PATCH 196/256] [6913] Fixed guild creation after adding stronger checks. Fixed _return_ typo in guild charter sign code. Merged some sql queries into one. Signed-off-by: ApoC --- src/game/PetitionsHandler.cpp | 60 +++++++++++++++-------------------- src/shared/revision_nr.h | 2 +- 2 files changed, 26 insertions(+), 36 deletions(-) diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index 857143749..e41036626 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -250,15 +250,16 @@ void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data) // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?) uint32 petitionguid_low = GUID_LOPART(petitionguid); - QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid, type FROM petition WHERE petitionguid = '%u'", petitionguid_low); + QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low); if(!result) { sLog.outError("any petition on server..."); return; } Field *fields = result->Fetch(); - uint32 type = fields[1].GetUInt32(); + uint32 type = fields[0].GetUInt32(); delete result; + // if guild petition and has guild => error, return; if(type==9 && _player->GetGuildId()) return; @@ -317,6 +318,7 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) QueryResult *result = CharacterDatabase.PQuery( "SELECT ownerguid, name, " " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs " + "type " "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); if(result) @@ -325,6 +327,7 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); name = fields[1].GetCppString(); signs = fields[2].GetUInt8(); + type = fields[3].GetUInt32(); delete result; } else @@ -333,20 +336,6 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) return; } - QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - - if(result2) - { - Field* fields = result2->Fetch(); - type = fields[0].GetUInt32(); - delete result2; - } - else - { - sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); - return; - } - WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*13)); data << GUID_LOPART(petitionguid); // guild/team guid (in mangos always same as GUID_LOPART(petition guid) data << ownerguid; // charter owner guid @@ -398,13 +387,13 @@ void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data) if(!item) return; - QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - if(result2) + if(result) { - Field* fields = result2->Fetch(); + Field* fields = result->Fetch(); type = fields[0].GetUInt32(); - delete result2; + delete result; } else { @@ -549,11 +538,9 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD); return; } - return; } - signs += 1; - if(signs > type) // client signs maximum + if(++signs > type) // client signs maximum return; //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account @@ -637,14 +624,26 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) uint8 signs = 0; uint64 petitionguid, plguid; - uint32 type; + uint32 type, junk; Player *player; - recv_data >> type; + recv_data >> junk; // this is not petition type! recv_data >> petitionguid; // petition guid recv_data >> plguid; // player guid - sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid)); player = ObjectAccessor::FindPlayer(plguid); + if (!player) + return; + + QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); + if (!result) + return; + + Field *fields = result->Fetch(); + type = fields[0].GetUInt32(); + delete result; + + sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid)); + if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() ) { if(type != 9) @@ -695,15 +694,6 @@ void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data) } } - QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - if(!result) - { - sLog.outError("any petition on server..."); - return; - } - - delete result; - result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); // result==NULL also correct charter without signs if(result) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0ec0c3ee2..b1580de0a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6912" + #define REVISION_NR "6913" #endif // __REVISION_NR_H__ From 96ea56ee8f03b9b8a3a72c3ade704586a46a7e4f Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Tue, 16 Dec 2008 07:57:08 +0300 Subject: [PATCH 197/256] Compile fix --- src/game/World.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/game/World.h b/src/game/World.h index ea2d67892..9e5b2ad50 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -183,10 +183,6 @@ enum WorldConfigs CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, CONFIG_SKILL_MILLING, - CONFIG_ARENA_RATING_DISCARD_TIMER, - CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS, - CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, - CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, CONFIG_VALUE_COUNT }; From 34bef19e63584752b673f23b414b79d5dc70ff5a Mon Sep 17 00:00:00 2001 From: ApoC Date: Tue, 16 Dec 2008 13:47:50 +0100 Subject: [PATCH 198/256] [6914] Fixed missing comma. Signed-off-by: ApoC --- src/game/PetitionsHandler.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index e41036626..980110d25 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -317,7 +317,7 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) QueryResult *result = CharacterDatabase.PQuery( "SELECT ownerguid, name, " - " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs " + " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, " "type " "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index b1580de0a..5bc9d2bd1 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6913" + #define REVISION_NR "6914" #endif // __REVISION_NR_H__ From f1cc9dc3196e0dc64b02bb5e1dbb00c40c4e9717 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Tue, 16 Dec 2008 18:24:30 +0300 Subject: [PATCH 199/256] * Add some aura names and comments * Implement 256 SPELL_AURA_NO_REAGENT_USE aura * Move no reagent check to Player::CanNoReagentCast * Add some func for get/check SpellClassMask (used in some new aura/effect) Signed-off-by: DiSlord --- src/game/Player.cpp | 18 +++++++++++ src/game/Player.h | 1 + src/game/Spell.cpp | 13 ++++---- src/game/SpellAuraDefines.h | 18 +++++------ src/game/SpellAuras.cpp | 64 ++++++++++++++++++++++++++++--------- src/game/SpellAuras.h | 4 +++ 6 files changed, 88 insertions(+), 30 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index a37a7634a..b7909f51c 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2339,6 +2339,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); @@ -18353,6 +18356,21 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons return false; } +bool Player::CanNoReagentCast(SpellEntry const* spellInfo) +{ + // 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 + uint64 noReagentMask_0_1 = GetUInt64Value(PLAYER_NO_REAGENT_COST_1); + uint32 noReagentMask_2 = GetUInt64Value(PLAYER_NO_REAGENT_COST_1+2); + if (spellInfo->SpellFamilyFlags & noReagentMask_0_1 || + spellInfo->SpellFamilyFlags2 & noReagentMask_2) + return true; + return false; +} + void Player::RemoveItemDependentAurasAndCasts( Item * pItem ) { AuraMap& auras = GetAuras(); diff --git a/src/game/Player.h b/src/game/Player.h index ba9c251c1..86c425b6b 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1102,6 +1102,7 @@ class MANGOS_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); 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); } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 297ddf6be..44d5ce31d 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3260,11 +3260,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++) { @@ -4693,8 +4691,11 @@ 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))) + bool needReagentCheck = true; + if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->CanNoReagentCast(m_spellInfo)) + needReagentCheck = false; + + if (needReagentCheck) { for(uint32 i=0;i<8;i++) { diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index f0100f8d7..cb5951a5f 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -295,17 +295,17 @@ enum AuraType 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_SHIELD = 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, SPELL_AURA_262 = 262, - SPELL_AURA_263 = 263, + SPELL_AURA_ALLOW_ONLY_ABILITY = 263, SPELL_AURA_264 = 264, SPELL_AURA_265 = 265, SPELL_AURA_266 = 266, @@ -318,11 +318,11 @@ enum AuraType SPELL_AURA_273 = 273, SPELL_AURA_274 = 274, SPELL_AURA_275 = 275, - SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell + SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done SPELL_AURA_277 = 277, - SPELL_AURA_278 = 278, + SPELL_AURA_MOD_DISARM_RANGED = 278, SPELL_AURA_279 = 279, - SPELL_AURA_280 = 280, + SPELL_AURA_MOD_TARGET_ARMOR_PCT = 280, SPELL_AURA_MOD_HONOR_GAIN = 281, SPELL_AURA_MOD_BASE_HEALTH_PCT = 282, SPELL_AURA_MOD_HEALING_RECEIVED = 283, // Possibly only for some spell family class spells diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index fb6fe333a..809ee2462 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -296,42 +296,42 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &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::HandleUnused, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL &Aura::HandleUnused, //247 unused &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst &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::HandleNULL, //252 - &Aura::HandleNULL, //253 - &Aura::HandleNULL, //254 - &Aura::HandleNULL, //255 SPELL_AURA_MOD_DAMAGE_PERCENT_MECHANIC - &Aura::HandleNULL, //256 - &Aura::HandleNULL, //257 SPELL_AURA_MOD_TARGET_RESIST_BY_SPELL_CLASS + &Aura::HandleNULL, //252 haste all? + &Aura::HandleNULL, //253 SPELL_AURA_MOD_BLOCK_CRIT_CHANCE + &Aura::HandleNULL, //254 SPELL_AURA_MOD_DISARM_SHIELD disarm Shield + &Aura::HandleNULL, //255 SPELL_AURA_MOD_MECHANIC_DAMAGE_TAKEN_PERCENT + &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::HandleNULL, //259 corrupt healing over time spell &Aura::HandleNULL, //260 &Aura::HandleNULL, //261 out of phase? &Aura::HandleNULL, //262 - &Aura::HandleNULL, //263 melee AOE + &Aura::HandleNULL, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilites set in SpellClassMask &Aura::HandleNULL, //264 unused &Aura::HandleNULL, //265 unused &Aura::HandleNULL, //266 unused &Aura::HandleNULL, //267 some immunity? - &Aura::HandleNULL, //268 attack power from stat X + &Aura::HandleNULL, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT &Aura::HandleNULL, //269 ignore DR effects? &Aura::HandleNULL, //270 &Aura::HandleNULL, //271 increase damage done? &Aura::HandleNULL, //272 reduce spell cast time? &Aura::HandleNULL, //273 &Aura::HandleNULL, //274 proc free shot? - &Aura::HandleNULL, //275 ignore shapeshift? + &Aura::HandleNULL, //275 ignore shapeshift Use SpellClassMask for spell select &Aura::HandleNULL, //276 mod damage % mechanic? - &Aura::HandleNULL, //277 increase max targets? - &Aura::HandleNULL, //278 disarm/silence + &Aura::HandleNULL, //277 increase max targets? Use SpellClassMask for spell select + &Aura::HandleNULL, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon &Aura::HandleNULL, //279 - &Aura::HandleNULL, //280 ignore armor? - &Aura::HandleNULL, //281 increase honor gain? + &Aura::HandleNULL, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT + &Aura::HandleNULL, //281 SPELL_AURA_MOD_HONOR_GAIN &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT &Aura::HandleNULL //283 SPD/heal from AP? }; @@ -1171,7 +1171,19 @@ void Aura::UpdateSlotCounterAndDuration(bool add) SetAuraCharges(count); SendAuraUpdate(false); } - +bool Aura::isAffectedOnSpell(SpellEntry const *spell) +{ + // Check family name + if (spell->SpellFamilyName != m_spellProto->SpellFamilyName) + return false; + // Check EffectClassMask + uint32 const *ptr = getAuraSpellClassMask(); + if (((uint64*)ptr)[0] & spell->SpellFamilyFlags) + return true; + if (ptr[2] & spell->SpellFamilyFlags2) + return true; + return false; +} /*********************************************************/ /*** BASIC AURA FUNCTION ***/ /*********************************************************/ @@ -5192,6 +5204,28 @@ void Aura::HandleModPowerCost(bool apply, bool Real) 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; + uint32 mask[3] = {0, 0, 0}; + Unit::AuraList const& noReagent = m_target->GetAurasByType(SPELL_AURA_NO_REAGENT_USE); + for(Unit::AuraList::const_iterator i = noReagent.begin(); i != noReagent.end(); ++i) + { + uint32 const *ptr = (*i)->getAuraSpellClassMask(); + mask[0]|=ptr[0]; + mask[1]|=ptr[1]; + mask[2]|=ptr[2]; + } + + 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 ***/ /*********************************************************/ diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 09ee97eb5..387b0a36c 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -211,6 +211,7 @@ class MANGOS_DLL_SPEC Aura void HandleArenaPreparation(bool apply, bool Real); void HandleAuraConvertRune(bool apply, bool Real); void HandleAuraIncreaseBaseHealthPercent(bool Apply, bool Real); + void HandleNoReagentUseAura(bool Apply, bool Real); virtual ~Aura(); @@ -302,6 +303,9 @@ class MANGOS_DLL_SPEC Aura void PeriodicTick(); void PeriodicDummyTick(); + + inline uint32 const *getAuraSpellClassMask() {return m_spellProto->EffectSpellClassMaskA + m_effIndex * 3; } + bool isAffectedOnSpell(SpellEntry const *spell); protected: Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL); From fc684dc737c7bdfdd6eb20ea96d534780da10343 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 16 Dec 2008 19:19:31 +0300 Subject: [PATCH 200/256] Simplify check in reagent cheking code. Small code cleanups after recent commit. --- src/game/Player.cpp | 4 +++- src/game/Player.h | 2 +- src/game/Spell.cpp | 6 +----- src/game/SpellAuras.cpp | 4 +++- src/game/SpellAuras.h | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index b7909f51c..cb7146f25 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18356,18 +18356,20 @@ bool Player::HasItemFitToSpellReqirements(SpellEntry const* spellInfo, Item cons return false; } -bool Player::CanNoReagentCast(SpellEntry const* spellInfo) +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 uint64 noReagentMask_0_1 = GetUInt64Value(PLAYER_NO_REAGENT_COST_1); uint32 noReagentMask_2 = GetUInt64Value(PLAYER_NO_REAGENT_COST_1+2); if (spellInfo->SpellFamilyFlags & noReagentMask_0_1 || spellInfo->SpellFamilyFlags2 & noReagentMask_2) return true; + return false; } diff --git a/src/game/Player.h b/src/game/Player.h index 86c425b6b..53d676b9d 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1102,7 +1102,7 @@ class MANGOS_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); + 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); } diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 44d5ce31d..07aea8100 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -4691,11 +4691,7 @@ uint8 Spell::CheckItems() focusObject = ok; // game object found in range } - bool needReagentCheck = true; - if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->CanNoReagentCast(m_spellInfo)) - needReagentCheck = false; - - if (needReagentCheck) + if (!p_caster->CanNoReagentCast(m_spellInfo)) { for(uint32 i=0;i<8;i++) { diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 809ee2462..4a8425dc7 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -1171,7 +1171,8 @@ void Aura::UpdateSlotCounterAndDuration(bool add) SetAuraCharges(count); SendAuraUpdate(false); } -bool Aura::isAffectedOnSpell(SpellEntry const *spell) + +bool Aura::isAffectedOnSpell(SpellEntry const *spell) const { // Check family name if (spell->SpellFamilyName != m_spellProto->SpellFamilyName) @@ -1184,6 +1185,7 @@ bool Aura::isAffectedOnSpell(SpellEntry const *spell) return true; return false; } + /*********************************************************/ /*** BASIC AURA FUNCTION ***/ /*********************************************************/ diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 387b0a36c..2ad9dd3c4 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -304,8 +304,8 @@ class MANGOS_DLL_SPEC Aura void PeriodicTick(); void PeriodicDummyTick(); - inline uint32 const *getAuraSpellClassMask() {return m_spellProto->EffectSpellClassMaskA + m_effIndex * 3; } - bool isAffectedOnSpell(SpellEntry const *spell); + uint32 const *getAuraSpellClassMask() const { return m_spellProto->EffectSpellClassMaskA + m_effIndex * 3; } + bool isAffectedOnSpell(SpellEntry const *spell) const; protected: Aura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL); From a33a7f67f7cbeea6dc103c142f66cbf4a4a0ab32 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Tue, 16 Dec 2008 22:43:18 +0300 Subject: [PATCH 201/256] * Implement 246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL Signed-off-by: DiSlord --- src/game/SpellAuraDefines.h | 2 +- src/game/Unit.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index cb5951a5f..fb0754a51 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -288,7 +288,7 @@ enum AuraType SPELL_AURA_243 = 243, SPELL_AURA_COMPREHEND_LANGUAGE = 244, SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS = 245, - SPELL_AURA_246 = 246, + SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL = 246, SPELL_AURA_247 = 247, SPELL_AURA_MOD_COMBAT_RESULT_CHANCE = 248, SPELL_AURA_CONVERT_RUNE = 249, diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 767808962..4d0854be4 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9319,6 +9319,8 @@ int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_in int32 mechanic = GetEffectMechanic(spellProto, effect_index); // Find total mod value (negative bonus) int32 durationMod_always = target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD, mechanic); + // Modify from SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL aura (stack always ?) + durationMod_always+=target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL, spellProto->Dispel); // Find max mod (negative bonus) int32 durationMod_not_stack = target->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK, mechanic); From 668c3d4b4c3ec0fc5d6f77c5f2f6eb07c1827362 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Tue, 16 Dec 2008 23:25:27 +0300 Subject: [PATCH 202/256] * Better implement 202 SPELL_AURA_IGNORE_COMBAT_RESULT based on SpellClassMask Signed-off-by: DiSlord --- src/game/Unit.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 4d0854be4..b8776457b 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -2307,21 +2307,21 @@ MeleeHitOutcome Unit::RollPhysicalOutcomeAgainst (Unit const *pVictim, WeaponAtt { // 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 + // Ignore combat result aura + AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); + for(AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i) { - AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); - for(AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i) + if (!(*i)->isAffectedOnSpell(spellInfo)) + continue; + // can't be dodged + switch((*i)->GetModifier()->m_miscvalue) { - // 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; - } - } + case MELEE_HIT_DODGE: dodge_chance = 0.0f; break; + case MELEE_HIT_BLOCK: block_chance = 0.0f; break; + case MELEE_HIT_PARRY: parry_chance = 0.0f; break; + default: + DEBUG_LOG("Spell %u SPELL_AURA_IGNORE_COMBAT_RESULT have unhandled state %d", (*i)->GetId(), (*i)->GetModifier()->m_miscvalue); + break; } } } From 3604f3fa1fdd09cfba4b61ee8a99c9fc75020784 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Wed, 17 Dec 2008 00:41:07 +0300 Subject: [PATCH 203/256] Fixed last comit comments, names --- src/game/Unit.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index b8776457b..d710d29ae 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -2308,12 +2308,11 @@ MeleeHitOutcome Unit::RollPhysicalOutcomeAgainst (Unit const *pVictim, WeaponAtt // Increase from SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL aura crit_chance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL, spellInfo->SchoolMask); // Ignore combat result aura - AuraList const& mCanNotBeDodge = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); - for(AuraList::const_iterator i = mCanNotBeDodge.begin(); i != mCanNotBeDodge.end(); ++i) + AuraList const& ignore = GetAurasByType(SPELL_AURA_IGNORE_COMBAT_RESULT); + for(AuraList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) { if (!(*i)->isAffectedOnSpell(spellInfo)) continue; - // can't be dodged switch((*i)->GetModifier()->m_miscvalue) { case MELEE_HIT_DODGE: dodge_chance = 0.0f; break; From 2c1f19d9978d6a853071dbdc82897f82877d0995 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Wed, 17 Dec 2008 00:46:53 +0300 Subject: [PATCH 204/256] Implement 275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Signed-off-by: DiSlord --- src/game/Spell.cpp | 23 ++++++++++++++++++----- src/game/SpellAuraDefines.h | 2 +- src/game/SpellAuras.cpp | 4 ++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 07aea8100..a8c1cad16 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -3385,12 +3385,25 @@ 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; + if ((m_spellInfo->Attributes & SPELL_ATTR_ONLY_STEALTHED) && !(m_caster->HasStealthAura())) + return SPELL_FAILED_ONLY_STEALTHED; + } } // caster state requirements diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index fb0754a51..2b429cae3 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -317,7 +317,7 @@ enum AuraType SPELL_AURA_272 = 272, SPELL_AURA_273 = 273, SPELL_AURA_274 = 274, - SPELL_AURA_275 = 275, + SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275, SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done SPELL_AURA_277 = 277, SPELL_AURA_MOD_DISARM_RANGED = 278, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 4a8425dc7..2377cc7fe 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -296,7 +296,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &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 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL + &Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL &Aura::HandleUnused, //247 unused &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst &Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE @@ -325,7 +325,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNULL, //272 reduce spell cast time? &Aura::HandleNULL, //273 &Aura::HandleNULL, //274 proc free shot? - &Aura::HandleNULL, //275 ignore shapeshift Use SpellClassMask for spell select + &Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select &Aura::HandleNULL, //276 mod damage % mechanic? &Aura::HandleNULL, //277 increase max targets? Use SpellClassMask for spell select &Aura::HandleNULL, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon From 213a10dcbdd10abe82166457c1a1a4c6d6ed5a61 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Wed, 17 Dec 2008 01:52:10 +0300 Subject: [PATCH 205/256] Implement 277 SPELL_AURA_MOD_MAX_AFFECTED_TARGETS Signed-off-by: DiSlord --- src/game/Spell.cpp | 8 ++++++++ src/game/SpellAuraDefines.h | 2 +- src/game/SpellAuras.cpp | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index a8c1cad16..5d5f6c87f 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1186,7 +1186,15 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) if(Player* modOwner = m_originalCaster->GetSpellModOwner()) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this); + // 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; + } switch(cur) { case TARGET_TOTEM_EARTH: diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 2b429cae3..80b53f1a2 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -319,7 +319,7 @@ enum AuraType SPELL_AURA_274 = 274, SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275, SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done - SPELL_AURA_277 = 277, + SPELL_AURA_MOD_MAX_AFFECTED_TARGETS = 277, SPELL_AURA_MOD_DISARM_RANGED = 278, SPELL_AURA_279 = 279, SPELL_AURA_MOD_TARGET_ARMOR_PCT = 280, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 2377cc7fe..4caac0d70 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -327,7 +327,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNULL, //274 proc free shot? &Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select &Aura::HandleNULL, //276 mod damage % mechanic? - &Aura::HandleNULL, //277 increase max targets? Use SpellClassMask for spell select + &Aura::HandleNoImmediateEffect, //277 SPELL_AURA_MOD_MAX_AFFECTED_TARGETS Use SpellClassMask for spell select &Aura::HandleNULL, //278 SPELL_AURA_MOD_DISARM_RANGED disarm ranged weapon &Aura::HandleNULL, //279 &Aura::HandleNULL, //280 SPELL_AURA_MOD_TARGET_ARMOR_PCT From 29b37f4b6c4b6c20dc0747bb0a030a92ba689ad7 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Wed, 17 Dec 2008 01:46:34 +0300 Subject: [PATCH 206/256] [6915] Fixed use uninitialized petition type variable in petition signing code. --- src/game/PetitionsHandler.cpp | 28 ++++++---------------------- src/shared/revision_nr.h | 2 +- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index 980110d25..50eab90e4 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -318,7 +318,7 @@ void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid) QueryResult *result = CharacterDatabase.PQuery( "SELECT ownerguid, name, " " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, " - "type " + " type " "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); if(result) @@ -449,17 +449,14 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) Field *fields; uint64 petitionguid; - uint32 type; uint8 unk; - uint64 ownerguid; recv_data >> petitionguid; // petition guid recv_data >> unk; - uint8 signs = 0; - QueryResult *result = CharacterDatabase.PQuery( "SELECT ownerguid, " - " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs " + " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, " + " type " "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid)); if(!result) @@ -469,8 +466,9 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) } fields = result->Fetch(); - ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); - signs = fields[1].GetUInt8(); + uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER); + uint8 signs = fields[1].GetUInt8(); + uint32 type = fields[2].GetUInt32(); delete result; @@ -488,20 +486,6 @@ void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data) return; } - QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid)); - - if(result2) - { - Field* fields = result2->Fetch(); - type = fields[0].GetUInt32(); - delete result2; - } - else - { - sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid)); - return; - } - if(type != 9) { if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 5bc9d2bd1..3b0aaa603 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6914" + #define REVISION_NR "6915" #endif // __REVISION_NR_H__ From 771f9b23757ac22c5ac4f8d2c0c52567163e4b7f Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 18 Dec 2008 03:02:49 +0300 Subject: [PATCH 207/256] [6916] Fixed typos in spell checking code. --- src/game/SpellMgr.cpp | 6 +++--- src/shared/revision_nr.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 605336504..d1b94fae2 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -2003,15 +2003,15 @@ bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg) } case SPELL_EFFECT_LEARN_SPELL: { - SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(spellInfo->EffectTriggerSpell[0]); + SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(spellInfo->EffectTriggerSpell[i]); if( !IsSpellValid(spellInfo2,pl,msg) ) { if(msg) { if(pl) - ChatHandler(pl).PSendSysMessage("Spell %u learn to broken spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[0]); + ChatHandler(pl).PSendSysMessage("Spell %u learn to broken spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[i]); else - sLog.outErrorDb("Spell %u learn to invalid spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[0]); + sLog.outErrorDb("Spell %u learn to invalid spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[i]); } return false; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 3b0aaa603..0ac441485 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6915" + #define REVISION_NR "6916" #endif // __REVISION_NR_H__ From 7891238bdee7ea03c564cc2d1a7ce104ea123ee1 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Thu, 18 Dec 2008 05:55:28 +0300 Subject: [PATCH 208/256] Level stats for >70 and new class. Data for new class levels <55 same as class 1 for same race (mostly). Also fox item_template data structure in mangos.sql (add data for new fields). --- sql/mangos.sql | 1468 ++++- .../12_mangos_player_levelstats.sql | 5023 +++++++++++++++++ 2 files changed, 6417 insertions(+), 74 deletions(-) create mode 100644 sql/wotlk_updates/12_mangos_player_levelstats.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index a10084869..87cb16eff 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -1671,79 +1671,79 @@ CREATE TABLE `item_template` ( LOCK TABLES `item_template` WRITE; /*!40000 ALTER TABLE `item_template` DISABLE KEYS */; INSERT INTO `item_template` VALUES -(25,2,7,-1,'Worn Shortsword',1542,1,0,1,35,7,21,32767,511,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,1,0,0,0,1,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(35,2,10,-1,'Bent Staff',472,1,0,1,47,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(36,2,4,-1,'Worn Mace',5194,1,0,1,38,7,21,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(37,2,0,-1,'Worn Axe',14029,1,0,1,38,7,21,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(38,4,0,-1,'Recruit\'s Shirt',9891,1,0,1,1,1,4,-1,-1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(39,4,1,-1,'Recruit\'s Pants',9892,0,0,1,5,1,7,32767,511,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(40,4,0,-1,'Recruit\'s Boots',10141,1,0,1,4,1,8,32767,511,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(43,4,0,-1,'Squire\'s Boots',9938,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(44,4,1,-1,'Squire\'s Pants',9937,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(45,4,0,-1,'Squire\'s Shirt',3265,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(47,4,0,-1,'Footpad\'s Shoes',9915,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(48,4,1,-1,'Footpad\'s Pants',9913,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(49,4,0,-1,'Footpad\'s Shirt',9906,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(51,4,0,-1,'Neophyte\'s Boots',9946,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(52,4,1,-1,'Neophyte\'s Pants',9945,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(53,4,0,-1,'Neophyte\'s Shirt',9944,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(55,4,0,-1,'Apprentice\'s Boots',9929,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(56,4,1,-1,'Apprentice\'s Robe',12647,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(57,4,1,-1,'Acolyte\'s Robe',12645,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(59,4,0,-1,'Acolyte\'s Shoes',3261,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(117,0,0,-1,'Tough Jerky',2473,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(120,4,1,-1,'Thug Pants',10006,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(121,4,0,-1,'Thug Boots',10008,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(127,4,0,-1,'Trapper\'s Shirt',9996,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(139,4,1,-1,'Brawler\'s Pants',9988,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(140,4,0,-1,'Brawler\'s Boots',9992,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(147,4,1,-1,'Rugged Trapper\'s Pants',9975,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(148,4,0,-1,'Rugged Trapper\'s Shirt',9976,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(153,4,2,-1,'Primitive Kilt',10050,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(154,4,0,-1,'Primitive Mantle',10058,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(159,0,0,-1,'Refreshing Spring Water',18084,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,430,0,-1,0,-1,59,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(1395,4,1,-1,'Apprentice\'s Pants',9924,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(1396,4,1,-1,'Acolyte\'s Pants',3260,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2070,0,0,-1,'Darnassian Bleu',6353,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2092,2,15,-1,'Worn Dagger',6442,1,0,1,35,7,13,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1600,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,3,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2101,1,2,-1,'Light Quiver',21328,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,14824,1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2102,1,3,-1,'Small Ammo Pouch',1816,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,14824,1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2105,4,0,-1,'Thug Shirt',10005,1,0,1,5,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2361,2,5,-1,'Battleworn Hammer',8690,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2362,4,6,-1,'Worn Wooden Shield',18730,0,0,1,7,1,14,32767,511,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,4,0,0,1,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2504,2,2,-1,'Worn Shortbow',8106,1,0,1,29,5,15,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,2,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2508,2,3,-1,'Old Blunderbuss',6606,1,0,1,27,5,26,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,3,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2512,6,2,-1,'Rough Arrow',5996,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2516,6,3,-1,'Light Shot',5998,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(2947,2,16,-1,'Small Throwing Knife',16754,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(3661,2,10,-1,'Handcrafted Staff',18530,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(4536,0,0,-1,'Shiny Red Apple',6410,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(4540,0,0,-1,'Tough Hunk of Bread',6399,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(4604,0,0,-1,'Forest Mushroom Cap',15852,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6096,4,0,-1,'Apprentice\'s Shirt',2163,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6097,4,0,-1,'Acolyte\'s Shirt',2470,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6098,4,1,-1,'Neophyte\'s Robe',12679,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6119,4,1,-1,'Neophyte\'s Robe',12681,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6123,4,1,-1,'Novice\'s Robe',12683,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6124,4,1,-1,'Novice\'s Pants',9987,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6125,4,0,-1,'Brawler\'s Harness',9995,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6126,4,1,-1,'Trapper\'s Pants',10002,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6127,4,0,-1,'Trapper\'s Boots',10003,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6129,4,1,-1,'Acolyte\'s Robe',12646,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6134,4,0,-1,'Primitive Mantle',10108,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6135,4,2,-1,'Primitive Kilt',10109,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6139,4,1,-1,'Novice\'s Robe',12684,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6140,4,1,-1,'Apprentice\'s Robe',12649,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6144,4,1,-1,'Neophyte\'s Robe',12680,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(6948,15,0,-1,'Hearthstone',6418,1,64,1,0,0,0,32767,511,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8690,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(12282,2,1,-1,'Worn Battleaxe',22291,1,0,1,43,8,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14646,12,0,-1,'Northshire Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5805,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14647,12,0,-1,'Coldridge Valley Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5841,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14648,12,0,-1,'Shadowglen Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5842,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14649,12,0,-1,'Valley of Trials Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5843,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14650,12,0,-1,'Camp Narache Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5844,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(14651,12,0,-1,'Deathknell Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5847,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0), -(25861,2,16,-1,'Crude Throwing Axe',20777,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,'internalItemHandler',0,0,0,0,0); +(25,2,7,-1,'Worn Shortsword',1542,1,0,1,35,7,21,32767,511,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,1,0,0,0,1,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(35,2,10,-1,'Bent Staff',472,1,0,1,47,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(36,2,4,-1,'Worn Mace',5194,1,0,1,38,7,21,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(37,2,0,-1,'Worn Axe',14029,1,0,1,38,7,21,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,3,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(38,4,0,-1,'Recruit\'s Shirt',9891,1,0,1,1,1,4,-1,-1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(39,4,1,-1,'Recruit\'s Pants',9892,0,0,1,5,1,7,32767,511,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(40,4,0,-1,'Recruit\'s Boots',10141,1,0,1,4,1,8,32767,511,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(43,4,0,-1,'Squire\'s Boots',9938,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(44,4,1,-1,'Squire\'s Pants',9937,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(45,4,0,-1,'Squire\'s Shirt',3265,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(47,4,0,-1,'Footpad\'s Shoes',9915,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(48,4,1,-1,'Footpad\'s Pants',9913,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(49,4,0,-1,'Footpad\'s Shirt',9906,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(51,4,0,-1,'Neophyte\'s Boots',9946,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(52,4,1,-1,'Neophyte\'s Pants',9945,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(53,4,0,-1,'Neophyte\'s Shirt',9944,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(55,4,0,-1,'Apprentice\'s Boots',9929,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(56,4,1,-1,'Apprentice\'s Robe',12647,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(57,4,1,-1,'Acolyte\'s Robe',12645,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(59,4,0,-1,'Acolyte\'s Shoes',3261,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(117,0,0,-1,'Tough Jerky',2473,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(120,4,1,-1,'Thug Pants',10006,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(121,4,0,-1,'Thug Boots',10008,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(127,4,0,-1,'Trapper\'s Shirt',9996,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(139,4,1,-1,'Brawler\'s Pants',9988,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(140,4,0,-1,'Brawler\'s Boots',9992,1,0,1,4,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(147,4,1,-1,'Rugged Trapper\'s Pants',9975,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(148,4,0,-1,'Rugged Trapper\'s Shirt',9976,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(153,4,2,-1,'Primitive Kilt',10050,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(154,4,0,-1,'Primitive Mantle',10058,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(159,0,0,-1,'Refreshing Spring Water',18084,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,430,0,-1,0,-1,59,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(1395,4,1,-1,'Apprentice\'s Pants',9924,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(1396,4,1,-1,'Acolyte\'s Pants',3260,0,0,1,4,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2070,0,0,-1,'Darnassian Bleu',6353,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2092,2,15,-1,'Worn Dagger',6442,1,0,1,35,7,13,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1600,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,3,0,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2101,1,2,-1,'Light Quiver',21328,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,14824,1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2102,1,3,-1,'Small Ammo Pouch',1816,1,0,1,4,1,18,2047,255,1,1,0,0,0,0,0,0,0,0,1,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,14824,1,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2105,4,0,-1,'Thug Shirt',10005,1,0,1,5,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2361,2,5,-1,'Battleworn Hammer',8690,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2362,4,6,-1,'Worn Wooden Shield',18730,0,0,1,7,1,14,32767,511,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,4,0,0,1,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2504,2,2,-1,'Worn Shortbow',8106,1,0,1,29,5,15,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,2,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2508,2,3,-1,'Old Blunderbuss',6606,1,0,1,27,5,26,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2300,3,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2512,6,2,-1,'Rough Arrow',5996,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2516,6,3,-1,'Light Shot',5998,1,0,1,10,0,24,2047,255,5,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(2947,2,16,-1,'Small Throwing Knife',16754,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(3661,2,10,-1,'Handcrafted Staff',18530,1,0,1,45,9,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,2,2,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(4536,0,0,-1,'Shiny Red Apple',6410,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(4540,0,0,-1,'Tough Hunk of Bread',6399,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(4604,0,0,-1,'Forest Mushroom Cap',15852,1,0,6,25,1,0,2047,255,5,1,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,433,0,-1,0,-1,11,1000,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6096,4,0,-1,'Apprentice\'s Shirt',2163,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6097,4,0,-1,'Acolyte\'s Shirt',2470,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6098,4,1,-1,'Neophyte\'s Robe',12679,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6119,4,1,-1,'Neophyte\'s Robe',12681,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6123,4,1,-1,'Novice\'s Robe',12683,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6124,4,1,-1,'Novice\'s Pants',9987,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6125,4,0,-1,'Brawler\'s Harness',9995,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6126,4,1,-1,'Trapper\'s Pants',10002,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6127,4,0,-1,'Trapper\'s Boots',10003,1,0,1,5,1,8,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6129,4,1,-1,'Acolyte\'s Robe',12646,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6134,4,0,-1,'Primitive Mantle',10108,1,0,1,1,1,4,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6135,4,2,-1,'Primitive Kilt',10109,0,0,1,5,1,7,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,8,0,0,0,0,0,30,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6139,4,1,-1,'Novice\'s Robe',12684,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6140,4,1,-1,'Apprentice\'s Robe',12649,0,0,1,4,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6144,4,1,-1,'Neophyte\'s Robe',12680,0,0,1,5,1,20,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,7,0,0,0,0,0,35,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(6948,15,0,-1,'Hearthstone',6418,1,64,1,0,0,0,32767,511,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8690,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(12282,2,1,-1,'Worn Battleaxe',22291,1,0,1,43,8,17,2047,255,2,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2900,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,1,0,0,0,0,25,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14646,12,0,-1,'Northshire Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5805,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14647,12,0,-1,'Coldridge Valley Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5841,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14648,12,0,-1,'Shadowglen Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5842,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14649,12,0,-1,'Valley of Trials Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5843,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14650,12,0,-1,'Camp Narache Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5844,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(14651,12,0,-1,'Deathknell Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5847,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(25861,2,16,-1,'Crude Throwing Axe',20777,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0); /*!40000 ALTER TABLE `item_template` ENABLE KEYS */; UNLOCK TABLES; @@ -4316,6 +4316,16 @@ INSERT INTO `player_levelstats` VALUES (1,1,68,140,93,129,32,50), (1,1,69,143,95,131,33,50), (1,1,70,145,96,133,33,51), +(1,1,71,148,97,140,33,53), +(1,1,72,156,99,143,33,54), +(1,1,73,162,101,148,33,55), +(1,1,74,162,102,148,34,55), +(1,1,75,165,104,150,34,56), +(1,1,76,171,106,156,34,57), +(1,1,77,171,108,157,35,58), +(1,1,78,174,109,159,35,58), +(1,1,79,181,111,165,35,59), +(1,1,80,184,113,168,36,60), (1,2,1,22,20,22,20,21), (1,2,2,23,21,23,21,22), (1,2,3,24,21,24,21,22), @@ -4386,6 +4396,16 @@ INSERT INTO `player_levelstats` VALUES (1,2,68,122,75,116,81,86), (1,2,69,124,76,118,82,88), (1,2,70,126,77,120,83,89), +(1,2,71,148,78,122,84,92), +(1,2,72,150,79,125,86,94), +(1,2,73,152,80,127,87,96), +(1,2,74,156,82,129,89,97), +(1,2,75,158,83,131,90,99), +(1,2,76,162,84,134,92,100), +(1,2,77,164,86,136,93,103), +(1,2,78,167,87,138,95,105), +(1,2,79,170,88,153,96,106), +(1,2,80,173,90,160,98,108), (1,4,1,21,23,21,20,20), (1,4,2,22,24,22,20,20), (1,4,3,23,26,22,20,21), @@ -4456,6 +4476,16 @@ INSERT INTO `player_levelstats` VALUES (1,4,68,92,153,86,38,57), (1,4,69,94,156,88,39,57), (1,4,70,95,158,89,39,58), +(1,4,71,97,161,90,39,60), +(1,4,72,99,164,92,40,60), +(1,4,73,100,167,94,40,61), +(1,4,74,102,170,95,41,62), +(1,4,75,104,173,97,41,63), +(1,4,76,105,176,98,41,64), +(1,4,77,107,179,100,42,65), +(1,4,78,109,183,106,42,66), +(1,4,79,111,186,107,43,67), +(1,4,80,113,189,109,43,69), (1,5,1,20,20,20,22,23), (1,5,2,20,20,20,23,24), (1,5,3,20,20,21,25,26), @@ -4526,6 +4556,96 @@ INSERT INTO `player_levelstats` VALUES (1,5,68,38,44,57,140,146), (1,5,69,39,44,57,143,149), (1,5,70,39,45,58,145,151), +(1,5,71,39,46,59,148,158), +(1,5,72,40,46,59,151,161), +(1,5,73,40,47,60,154,164), +(1,5,74,41,47,61,156,167), +(1,5,75,41,48,62,159,170), +(1,5,76,41,49,63,162,174), +(1,5,77,42,49,64,165,177), +(1,5,78,42,50,65,168,180), +(1,5,79,43,50,66,171,183), +(1,5,80,43,51,67,174,186), +(1,6,1,23,20,22,20,20), +(1,6,2,24,21,23,20,20), +(1,6,3,26,22,24,20,21), +(1,6,4,27,22,26,20,21), +(1,6,5,28,23,27,20,21), +(1,6,6,30,24,28,20,21), +(1,6,7,31,25,29,21,22), +(1,6,8,32,26,30,21,22), +(1,6,9,34,26,32,21,22), +(1,6,10,35,27,33,21,23), +(1,6,11,36,28,34,21,23), +(1,6,12,38,29,35,21,23), +(1,6,13,39,30,37,21,24), +(1,6,14,41,31,38,21,24), +(1,6,15,42,32,39,21,24), +(1,6,16,44,33,41,21,25), +(1,6,17,45,34,42,22,25), +(1,6,18,47,34,43,22,25), +(1,6,19,48,35,45,22,26), +(1,6,20,50,36,46,22,26), +(1,6,21,51,37,48,22,26), +(1,6,22,53,38,49,22,27), +(1,6,23,54,39,51,22,27), +(1,6,24,56,40,52,23,28), +(1,6,25,58,41,53,23,28), +(1,6,26,59,42,55,23,28), +(1,6,27,61,43,56,23,29), +(1,6,28,63,44,58,23,29), +(1,6,29,64,45,59,23,30), +(1,6,30,66,46,61,24,30), +(1,6,31,68,47,62,24,30), +(1,6,32,69,48,64,24,31), +(1,6,33,71,50,66,24,31), +(1,6,34,73,51,67,24,32), +(1,6,35,74,52,69,24,32), +(1,6,36,76,53,70,25,33), +(1,6,37,78,54,72,25,33), +(1,6,38,80,55,74,25,34), +(1,6,39,82,56,75,25,34), +(1,6,40,83,57,77,25,35), +(1,6,41,85,58,79,26,35), +(1,6,42,87,60,80,26,35), +(1,6,43,89,61,82,26,36), +(1,6,44,91,62,84,26,36), +(1,6,45,93,63,85,26,37), +(1,6,46,95,64,87,27,37), +(1,6,47,97,66,89,27,38), +(1,6,48,99,67,91,27,38), +(1,6,49,101,68,93,27,39), +(1,6,50,103,69,94,28,40), +(1,6,51,105,71,96,28,40), +(1,6,52,106,72,97,28,41), +(1,6,53,107,72,98,28,41), +(1,6,54,107,73,98,29,42), +(1,6,55,108,73,99,29,43), +(1,6,56,111,75,102,29,44), +(1,6,57,113,76,104,29,44), +(1,6,58,118,77,106,30,45), +(1,6,59,118,79,108,30,45), +(1,6,60,123,80,110,30,46), +(1,6,61,125,81,112,30,47), +(1,6,62,128,83,114,30,47), +(1,6,63,130,84,117,31,48), +(1,6,64,130,86,119,31,48), +(1,6,65,140,87,128,31,49), +(1,6,66,143,89,131,31,50), +(1,6,67,146,90,133,32,50), +(1,6,68,148,92,135,32,51), +(1,6,69,151,93,138,32,52), +(1,6,70,154,95,140,32,52), +(1,6,71,162,97,144,33,53), +(1,6,72,164,98,146,33,54), +(1,6,73,165,100,148,33,55), +(1,6,74,166,102,151,33,55), +(1,6,75,169,103,154,34,56), +(1,6,76,172,105,157,34,57), +(1,6,77,175,107,157,34,58), +(1,6,78,176,108,157,34,58), +(1,6,79,177,110,157,35,59), +(1,6,80,180,112,160,35,60), (1,8,1,20,20,20,23,22), (1,8,2,20,20,20,24,23), (1,8,3,20,20,21,26,25), @@ -4596,6 +4716,16 @@ INSERT INTO `player_levelstats` VALUES (1,8,68,32,38,50,146,140), (1,8,69,33,39,50,149,143), (1,8,70,33,39,51,151,145), +(1,8,71,33,39,52,154,152), +(1,8,72,33,40,53,160,155), +(1,8,73,33,40,54,160,158), +(1,8,74,34,41,54,163,160), +(1,8,75,34,41,55,166,163), +(1,8,76,34,41,56,169,166), +(1,8,77,35,42,57,172,169), +(1,8,78,35,42,57,175,173), +(1,8,79,35,43,58,178,176), +(1,8,80,36,43,59,181,179), (1,9,1,20,20,21,22,22), (1,9,2,20,20,22,23,23), (1,9,3,21,21,22,24,24), @@ -4666,6 +4796,16 @@ INSERT INTO `player_levelstats` VALUES (1,9,68,50,57,74,129,127), (1,9,69,50,57,75,131,129), (1,9,70,51,58,76,133,131), +(1,9,71,52,59,78,135,146), +(1,9,72,53,59,79,138,148), +(1,9,73,54,60,80,140,151), +(1,9,74,54,61,89,143,154), +(1,9,75,55,62,91,145,156), +(1,9,76,56,63,92,148,159), +(1,9,77,57,64,93,151,162), +(1,9,78,57,65,95,153,165), +(1,9,79,58,66,96,156,168), +(1,9,80,59,67,97,159,170), (2,1,1,26,17,24,17,23), (2,1,2,27,18,25,17,23), (2,1,3,29,19,26,17,24), @@ -4736,6 +4876,16 @@ INSERT INTO `player_levelstats` VALUES (2,1,68,143,90,131,29,53), (2,1,69,146,92,133,30,53), (2,1,70,148,93,135,30,54), +(2,1,71,157,94,142,30,55), +(2,1,72,162,96,148,30,56), +(2,1,73,165,98,150,30,57), +(2,1,74,168,99,153,31,57), +(2,1,75,170,101,154,31,58), +(2,1,76,172,103,156,31,59), +(2,1,77,174,105,159,32,60), +(2,1,78,179,106,162,32,60), +(2,1,79,184,108,167,32,61), +(2,1,80,187,110,170,33,62), (2,3,1,23,20,23,17,24), (2,3,2,23,21,24,18,25), (2,3,3,24,23,25,18,25), @@ -4806,6 +4956,16 @@ INSERT INTO `player_levelstats` VALUES (2,3,68,65,143,107,72,84), (2,3,69,66,146,108,73,85), (2,3,70,67,148,110,74,86), +(2,3,71,68,151,112,75,87), +(2,3,72,69,154,114,76,88), +(2,3,73,70,157,116,77,90), +(2,3,74,71,160,118,79,91), +(2,3,75,72,163,120,80,93), +(2,3,76,73,166,122,81,94), +(2,3,77,74,169,124,83,96), +(2,3,78,75,172,126,84,97), +(2,3,79,76,175,128,85,99), +(2,3,80,77,178,130,87,100), (2,4,1,24,20,23,17,23), (2,4,2,25,21,24,17,23), (2,4,3,25,23,24,17,24), @@ -4876,6 +5036,96 @@ INSERT INTO `player_levelstats` VALUES (2,4,68,95,150,88,35,59), (2,4,69,97,153,90,36,60), (2,4,70,98,155,91,36,61), +(2,4,71,100,158,92,36,62), +(2,4,72,102,161,94,37,62), +(2,4,73,103,164,99,37,63), +(2,4,74,105,167,100,38,64), +(2,4,75,107,170,102,38,65), +(2,4,76,108,173,102,38,66), +(2,4,77,110,176,102,39,67), +(2,4,78,112,180,103,39,68), +(2,4,79,114,183,105,40,69), +(2,4,80,116,186,107,40,70), +(2,6,1,26,17,24,17,23), +(2,6,2,27,18,25,17,23), +(2,6,3,29,19,26,17,24), +(2,6,4,30,19,27,17,24), +(2,6,5,31,20,29,17,24), +(2,6,6,32,21,30,17,24), +(2,6,7,34,22,31,18,25), +(2,6,8,35,23,32,18,25), +(2,6,9,37,24,34,18,25), +(2,6,10,38,24,35,18,26), +(2,6,11,39,25,36,18,26), +(2,6,12,41,26,37,18,26), +(2,6,13,42,27,39,18,27), +(2,6,14,44,28,40,18,27), +(2,6,15,45,29,41,18,27), +(2,6,16,47,30,43,19,28), +(2,6,17,48,31,44,19,28), +(2,6,18,50,32,45,19,28), +(2,6,19,51,33,47,19,29), +(2,6,20,53,34,48,19,29), +(2,6,21,54,34,50,19,29), +(2,6,22,56,35,51,19,30), +(2,6,23,57,36,52,20,30), +(2,6,24,59,37,54,20,30), +(2,6,25,60,38,55,20,31), +(2,6,26,62,39,57,20,31), +(2,6,27,64,40,58,20,32), +(2,6,28,65,41,60,20,32), +(2,6,29,67,43,61,21,32), +(2,6,30,69,44,63,21,33), +(2,6,31,70,45,64,21,33), +(2,6,32,72,46,66,21,34), +(2,6,33,74,47,67,21,34), +(2,6,34,76,48,69,21,35), +(2,6,35,77,49,71,22,35), +(2,6,36,79,50,72,22,36), +(2,6,37,81,51,74,22,36), +(2,6,38,83,52,76,22,36), +(2,6,39,84,53,77,22,37), +(2,6,40,86,55,79,23,37), +(2,6,41,88,56,81,23,38), +(2,6,42,90,57,82,23,38), +(2,6,43,92,58,84,23,39), +(2,6,44,94,59,86,23,39), +(2,6,45,96,60,87,24,40), +(2,6,46,98,62,89,24,40), +(2,6,47,100,63,91,24,41), +(2,6,48,101,64,93,24,41), +(2,6,49,103,65,94,25,42), +(2,6,50,105,66,96,25,42), +(2,6,51,107,68,98,25,43), +(2,6,52,109,69,100,25,43), +(2,6,53,110,69,100,25,44), +(2,6,54,111,70,101,26,45), +(2,6,55,111,70,101,26,45), +(2,6,56,114,72,104,26,46), +(2,6,57,116,73,106,26,46), +(2,6,58,118,74,108,27,47), +(2,6,59,124,76,110,27,47), +(2,6,60,126,77,112,27,48), +(2,6,61,128,78,114,27,49), +(2,6,62,131,80,116,27,49), +(2,6,63,133,81,119,28,50), +(2,6,64,136,83,121,28,50), +(2,6,65,136,84,123,28,51), +(2,6,66,142,86,126,28,52), +(2,6,67,145,87,128,29,52), +(2,6,68,147,89,130,29,53), +(2,6,69,150,90,133,29,54), +(2,6,70,157,92,135,29,54), +(2,6,71,160,94,138,30,55), +(2,6,72,163,95,140,30,56), +(2,6,73,166,97,151,30,57), +(2,6,74,169,99,154,30,57), +(2,6,75,172,100,156,31,58), +(2,6,76,175,102,160,31,59), +(2,6,77,179,104,162,31,60), +(2,6,78,182,105,165,31,60), +(2,6,79,191,107,168,32,61), +(2,6,80,194,109,171,32,62), (2,7,1,24,17,23,18,25), (2,7,2,25,17,24,19,26), (2,7,3,26,18,25,20,27), @@ -4946,6 +5196,16 @@ INSERT INTO `player_levelstats` VALUES (2,7,68,102,59,113,102,119), (2,7,69,103,60,114,103,121), (2,7,70,105,61,116,105,123), +(2,7,71,106,62,118,117,125), +(2,7,72,108,63,120,119,128), +(2,7,73,110,64,122,122,130), +(2,7,74,112,65,125,124,132), +(2,7,75,114,66,127,126,134), +(2,7,76,116,67,129,128,137), +(2,7,77,117,68,131,128,139), +(2,7,78,119,69,133,133,141), +(2,7,79,121,70,136,135,144), +(2,7,80,123,71,138,137,146), (2,9,1,23,17,23,19,25), (2,9,2,23,17,24,20,26), (2,9,3,24,18,24,21,27), @@ -5016,6 +5276,16 @@ INSERT INTO `player_levelstats` VALUES (2,9,68,53,54,76,126,130), (2,9,69,53,54,77,128,132), (2,9,70,54,55,78,130,134), +(2,9,71,55,56,88,134,145), +(2,9,72,56,56,89,135,147), +(2,9,73,57,57,90,137,150), +(2,9,74,57,58,91,142,153), +(2,9,75,58,59,93,142,155), +(2,9,76,59,60,94,145,158), +(2,9,77,60,61,95,148,161), +(2,9,78,60,62,97,150,164), +(2,9,79,61,63,98,153,167), +(2,9,80,62,64,99,156,169), (3,1,1,25,16,25,19,19), (3,1,2,26,17,26,19,19), (3,1,3,28,18,27,19,20), @@ -5086,6 +5356,16 @@ INSERT INTO `player_levelstats` VALUES (3,1,68,142,89,132,31,49), (3,1,69,145,91,134,32,49), (3,1,70,147,92,136,32,50), +(3,1,71,150,93,138,32,51), +(3,1,72,152,95,141,32,52), +(3,1,73,164,97,151,32,53), +(3,1,74,164,98,151,33,53), +(3,1,75,170,100,156,33,54), +(3,1,76,173,102,160,33,55), +(3,1,77,173,104,160,34,56), +(3,1,78,176,105,162,34,56), +(3,1,79,183,107,168,34,57), +(3,1,80,186,109,171,35,58), (3,2,1,24,16,25,19,20), (3,2,2,25,17,26,20,21), (3,2,3,26,17,27,20,21), @@ -5156,6 +5436,16 @@ INSERT INTO `player_levelstats` VALUES (3,2,68,124,71,119,80,85), (3,2,69,126,72,121,81,87), (3,2,70,128,73,123,82,88), +(3,2,71,150,74,125,83,89), +(3,2,72,152,75,128,85,91), +(3,2,73,156,76,130,86,93), +(3,2,74,158,78,132,88,94), +(3,2,75,161,79,134,89,96), +(3,2,76,164,80,137,91,97), +(3,2,77,166,82,139,92,99), +(3,2,78,170,83,141,94,101), +(3,2,79,172,84,144,95,102), +(3,2,80,175,86,146,97,104), (3,3,1,22,19,24,19,20), (3,3,2,22,20,25,20,21), (3,3,3,23,22,26,20,21), @@ -5226,6 +5516,16 @@ INSERT INTO `player_levelstats` VALUES (3,3,68,64,142,108,74,80), (3,3,69,65,145,109,75,81), (3,3,70,66,147,111,76,82), +(3,3,71,67,150,113,77,83), +(3,3,72,68,153,115,78,84), +(3,3,73,69,156,117,79,86), +(3,3,74,70,159,119,81,87), +(3,3,75,71,162,121,82,89), +(3,3,76,72,165,123,83,90), +(3,3,77,73,168,125,85,92), +(3,3,78,74,171,127,86,93), +(3,3,79,75,174,129,87,95), +(3,3,80,76,177,131,89,96), (3,4,1,23,19,24,19,19), (3,4,2,24,20,25,19,19), (3,4,3,24,22,25,19,20), @@ -5296,6 +5596,16 @@ INSERT INTO `player_levelstats` VALUES (3,4,68,94,149,89,37,56), (3,4,69,96,152,91,38,56), (3,4,70,97,154,92,38,57), +(3,4,71,99,157,93,38,58), +(3,4,72,101,160,96,39,58), +(3,4,73,102,163,97,39,59), +(3,4,74,104,166,98,40,60), +(3,4,75,106,169,100,40,61), +(3,4,76,107,172,101,40,62), +(3,4,77,109,175,103,41,63), +(3,4,78,111,179,105,41,64), +(3,4,79,113,182,106,42,65), +(3,4,80,115,185,108,42,66), (3,5,1,22,16,23,21,22), (3,5,2,22,16,23,22,23), (3,5,3,22,16,24,24,25), @@ -5366,6 +5676,96 @@ INSERT INTO `player_levelstats` VALUES (3,5,68,40,40,59,139,145), (3,5,69,41,40,60,142,148), (3,5,70,41,41,61,144,150), +(3,5,71,41,42,62,147,153), +(3,5,72,42,42,62,150,163), +(3,5,73,42,43,63,153,166), +(3,5,74,43,43,64,155,170), +(3,5,75,43,44,65,158,173), +(3,5,76,43,45,66,161,176), +(3,5,77,44,45,67,164,179), +(3,5,78,44,46,68,167,182), +(3,5,79,45,46,69,170,184), +(3,5,80,45,47,70,173,189), +(3,6,1,25,16,25,19,19), +(3,6,2,26,17,26,19,19), +(3,6,3,28,18,27,19,20), +(3,6,4,29,18,28,19,20), +(3,6,5,30,19,30,19,20), +(3,6,6,31,20,31,19,20), +(3,6,7,33,21,32,20,21), +(3,6,8,34,22,33,20,21), +(3,6,9,36,23,35,20,21), +(3,6,10,37,23,36,20,22), +(3,6,11,38,24,37,20,22), +(3,6,12,40,25,38,20,22), +(3,6,13,41,26,40,20,23), +(3,6,14,43,27,41,20,23), +(3,6,15,44,28,42,20,23), +(3,6,16,46,29,44,21,24), +(3,6,17,47,30,45,21,24), +(3,6,18,49,31,46,21,24), +(3,6,19,50,32,48,21,25), +(3,6,20,52,33,49,21,25), +(3,6,21,53,34,51,21,26), +(3,6,22,55,34,52,21,26), +(3,6,23,56,35,53,21,26), +(3,6,24,58,36,55,22,27), +(3,6,25,59,37,56,22,27), +(3,6,26,61,38,58,22,27), +(3,6,27,63,39,59,22,28), +(3,6,28,64,41,61,22,28), +(3,6,29,66,42,62,22,29), +(3,6,30,68,43,64,23,29), +(3,6,31,69,44,65,23,30), +(3,6,32,71,45,67,23,30), +(3,6,33,73,46,68,23,30), +(3,6,34,75,47,70,23,31), +(3,6,35,76,48,72,24,31), +(3,6,36,78,49,73,24,32), +(3,6,37,80,50,75,24,32), +(3,6,38,82,51,76,24,33), +(3,6,39,84,52,78,24,33), +(3,6,40,85,54,80,24,34), +(3,6,41,87,55,81,25,34), +(3,6,42,89,56,83,25,35), +(3,6,43,91,57,85,25,35), +(3,6,44,93,58,87,25,36), +(3,6,45,95,59,88,26,36), +(3,6,46,97,61,90,26,37), +(3,6,47,99,62,92,26,37), +(3,6,48,101,63,94,26,38), +(3,6,49,102,64,95,26,38), +(3,6,50,104,65,97,27,39), +(3,6,51,106,67,99,27,39), +(3,6,52,108,68,99,27,40), +(3,6,53,109,68,101,27,40), +(3,6,54,110,69,101,28,41), +(3,6,55,110,69,102,28,41), +(3,6,56,113,71,105,28,42), +(3,6,57,118,72,107,28,42), +(3,6,58,120,73,109,29,43), +(3,6,59,123,75,111,29,43), +(3,6,60,125,76,113,29,44), +(3,6,61,126,77,115,29,45), +(3,6,62,127,79,117,29,45), +(3,6,63,129,80,120,30,46), +(3,6,64,132,82,122,30,46), +(3,6,65,135,83,124,30,47), +(3,6,66,137,85,127,30,48), +(3,6,67,144,86,129,31,48), +(3,6,68,146,88,131,31,49), +(3,6,69,149,89,133,31,50), +(3,6,70,152,91,136,31,50), +(3,6,71,154,93,139,32,51), +(3,6,72,157,94,141,32,52), +(3,6,73,160,96,144,32,53), +(3,6,74,163,98,146,32,53), +(3,6,75,166,99,150,33,54), +(3,6,76,169,101,152,33,55), +(3,6,77,172,103,155,33,56), +(3,6,78,176,104,157,33,56), +(3,6,79,179,106,160,34,57), +(3,6,80,182,108,163,34,58), (4,1,1,20,25,21,20,20), (4,1,2,21,26,22,20,20), (4,1,3,23,27,23,20,21), @@ -5436,6 +5836,16 @@ INSERT INTO `player_levelstats` VALUES (4,1,68,138,98,128,32,50), (4,1,69,140,100,130,33,50), (4,1,70,142,101,132,33,51), +(4,1,71,145,102,134,33,52), +(4,1,72,147,104,137,33,53), +(4,1,73,150,106,139,33,54), +(4,1,74,153,107,142,34,54), +(4,1,75,156,109,144,34,55), +(4,1,76,159,111,148,34,56), +(4,1,77,162,113,150,35,57), +(4,1,78,165,114,152,35,57), +(4,1,79,178,116,164,35,58), +(4,1,80,181,118,167,36,59), (4,3,1,17,28,20,20,21), (4,3,2,17,29,21,21,22), (4,3,3,18,31,22,21,22), @@ -5506,6 +5916,16 @@ INSERT INTO `player_levelstats` VALUES (4,3,68,59,151,104,75,81), (4,3,69,60,154,105,76,82), (4,3,70,61,156,107,77,83), +(4,3,71,62,159,109,78,84), +(4,3,72,63,162,111,79,85), +(4,3,73,64,165,113,80,87), +(4,3,74,65,168,115,82,88), +(4,3,75,66,171,117,83,90), +(4,3,76,67,174,119,84,91), +(4,3,77,68,177,121,86,93), +(4,3,78,69,180,123,87,94), +(4,3,79,70,190,125,91,96), +(4,3,80,71,193,127,93,97), (4,4,1,18,28,20,20,20), (4,4,2,19,29,21,20,20), (4,4,3,20,31,21,20,21), @@ -5576,6 +5996,16 @@ INSERT INTO `player_levelstats` VALUES (4,4,68,89,158,85,38,57), (4,4,69,91,160,87,39,57), (4,4,70,92,163,88,39,58), +(4,4,71,94,166,90,39,59), +(4,4,72,96,169,91,40,59), +(4,4,73,97,172,93,40,60), +(4,4,74,99,175,94,41,61), +(4,4,75,101,178,96,41,62), +(4,4,76,102,181,97,41,63), +(4,4,77,104,184,99,42,64), +(4,4,78,106,188,101,42,65), +(4,4,79,108,191,102,43,66), +(4,4,80,110,194,104,43,67), (4,5,1,17,25,19,22,23), (4,5,2,17,25,19,23,24), (4,5,3,17,25,20,25,26), @@ -5646,6 +6076,96 @@ INSERT INTO `player_levelstats` VALUES (4,5,68,35,49,56,140,146), (4,5,69,36,49,56,143,149), (4,5,70,36,50,57,145,151), +(4,5,71,36,51,58,148,161), +(4,5,72,37,51,58,151,164), +(4,5,73,37,52,59,154,168), +(4,5,74,38,52,60,156,171), +(4,5,75,38,53,61,159,174), +(4,5,76,38,54,62,162,177), +(4,5,77,39,54,63,165,180), +(4,5,78,39,55,64,168,183), +(4,5,79,40,55,65,171,186), +(4,5,80,40,56,66,200,191), +(4,6,1,20,25,21,20,20), +(4,6,2,21,26,22,20,20), +(4,6,3,23,27,23,20,21), +(4,6,4,24,27,25,20,21), +(4,6,5,25,28,26,20,21), +(4,6,6,27,29,27,20,21), +(4,6,7,28,30,28,21,22), +(4,6,8,29,31,29,21,22), +(4,6,9,31,31,31,21,22), +(4,6,10,32,32,32,21,23), +(4,6,11,33,33,33,21,23), +(4,6,12,35,34,34,21,23), +(4,6,13,36,35,36,21,24), +(4,6,14,38,36,37,21,24), +(4,6,15,39,37,38,21,24), +(4,6,16,41,37,40,21,25), +(4,6,17,42,38,41,22,25), +(4,6,18,44,39,43,22,25), +(4,6,19,45,40,44,22,26), +(4,6,20,47,41,45,22,26), +(4,6,21,48,42,47,22,26), +(4,6,22,50,43,48,22,27), +(4,6,23,52,44,50,22,27), +(4,6,24,53,45,51,23,28), +(4,6,25,55,46,52,23,28), +(4,6,26,56,47,54,23,28), +(4,6,27,58,48,55,23,29), +(4,6,28,60,49,57,23,29), +(4,6,29,61,50,58,23,30), +(4,6,30,63,51,60,24,30), +(4,6,31,65,52,62,24,30), +(4,6,32,66,53,63,24,31), +(4,6,33,68,54,65,24,31), +(4,6,34,70,55,66,24,32), +(4,6,35,72,56,68,24,32), +(4,6,36,73,58,69,25,33), +(4,6,37,75,59,71,25,33), +(4,6,38,77,60,73,25,34), +(4,6,39,79,61,74,25,34), +(4,6,40,81,62,76,25,35), +(4,6,41,82,63,78,26,35), +(4,6,42,84,64,79,26,35), +(4,6,43,86,66,81,26,36), +(4,6,44,88,67,83,26,36), +(4,6,45,90,68,85,26,37), +(4,6,46,92,69,86,27,37), +(4,6,47,94,70,88,27,38), +(4,6,48,96,72,90,27,38), +(4,6,49,98,73,92,27,39), +(4,6,50,100,74,93,28,40), +(4,6,51,101,75,94,28,40), +(4,6,52,102,76,95,28,41), +(4,6,53,103,77,96,28,41), +(4,6,54,104,77,97,29,42), +(4,6,55,105,78,98,29,42), +(4,6,56,108,80,101,29,43), +(4,6,57,113,81,103,29,43), +(4,6,58,115,82,105,30,44), +(4,6,59,115,84,107,30,44), +(4,6,60,120,85,109,30,45), +(4,6,61,122,86,111,30,46), +(4,6,62,122,88,113,30,46), +(4,6,63,127,89,116,31,47), +(4,6,64,127,91,118,31,47), +(4,6,65,133,92,120,31,48), +(4,6,66,135,94,123,31,49), +(4,6,67,136,95,125,32,49), +(4,6,68,137,97,127,32,50), +(4,6,69,140,98,130,32,51), +(4,6,70,147,100,132,32,51), +(4,6,71,154,102,135,33,52), +(4,6,72,156,103,137,33,53), +(4,6,73,157,105,140,33,54), +(4,6,74,158,107,142,33,54), +(4,6,75,161,108,145,34,55), +(4,6,76,164,110,148,34,56), +(4,6,77,167,112,150,34,57), +(4,6,78,170,113,153,34,57), +(4,6,79,172,115,156,35,58), +(4,6,80,177,117,159,35,59), (4,11,1,18,25,19,22,22), (4,11,2,19,25,20,23,23), (4,11,3,19,26,20,24,24), @@ -5716,6 +6236,16 @@ INSERT INTO `player_levelstats` VALUES (4,11,68,71,73,80,116,129), (4,11,69,72,74,81,118,131), (4,11,70,73,75,82,120,133), +(4,11,71,75,76,83,122,135), +(4,11,72,76,78,85,125,138), +(4,11,73,77,79,86,127,140), +(4,11,74,78,80,88,131,143), +(4,11,75,80,81,89,133,145), +(4,11,76,81,82,91,134,148), +(4,11,77,82,83,92,136,151), +(4,11,78,84,85,94,138,153), +(4,11,79,85,86,95,141,156), +(4,11,80,86,87,97,143,159), (5,1,1,22,18,23,18,25), (5,1,2,23,19,24,18,25), (5,1,3,25,20,25,18,26), @@ -5786,6 +6316,16 @@ INSERT INTO `player_levelstats` VALUES (5,1,68,139,91,130,30,55), (5,1,69,142,93,132,31,55), (5,1,70,144,94,134,31,56), +(5,1,71,147,95,136,31,57), +(5,1,72,150,97,139,31,58), +(5,1,73,152,99,141,31,59), +(5,1,74,155,100,144,32,59), +(5,1,75,158,102,146,32,60), +(5,1,76,163,104,149,32,61), +(5,1,77,167,106,152,33,62), +(5,1,78,167,107,154,33,62), +(5,1,79,170,109,157,33,63), +(5,1,80,173,111,160,34,64), (5,4,1,20,21,22,18,25), (5,4,2,21,22,23,18,25), (5,4,3,22,24,23,18,26), @@ -5856,6 +6396,16 @@ INSERT INTO `player_levelstats` VALUES (5,4,68,91,151,87,36,61), (5,4,69,93,154,89,37,62), (5,4,70,94,156,90,37,63), +(5,4,71,96,159,91,37,64), +(5,4,72,98,162,93,38,64), +(5,4,73,99,165,95,38,65), +(5,4,74,101,168,96,39,66), +(5,4,75,103,171,98,39,67), +(5,4,76,104,174,99,39,68), +(5,4,77,106,177,101,40,69), +(5,4,78,108,181,103,40,70), +(5,4,79,110,184,104,41,71), +(5,4,80,112,187,106,41,72), (5,5,1,19,18,21,20,28), (5,5,2,19,18,21,21,29), (5,5,3,19,18,22,23,31), @@ -5926,6 +6476,96 @@ INSERT INTO `player_levelstats` VALUES (5,5,68,37,42,58,138,151), (5,5,69,38,42,58,141,154), (5,5,70,38,43,59,143,156), +(5,5,71,38,44,60,146,159), +(5,5,72,39,44,60,149,162), +(5,5,73,39,45,61,152,165), +(5,5,74,40,45,62,157,168), +(5,5,75,40,46,63,157,171), +(5,5,76,40,47,64,160,174), +(5,5,77,41,47,65,163,177), +(5,5,78,41,48,66,166,180), +(5,5,79,42,48,67,169,183), +(5,5,80,42,49,68,172,186), +(5,6,1,22,18,23,18,25), +(5,6,2,23,19,24,18,25), +(5,6,3,25,20,25,18,26), +(5,6,4,26,20,26,18,26), +(5,6,5,27,21,28,18,26), +(5,6,6,29,22,29,18,26), +(5,6,7,30,23,30,19,27), +(5,6,8,31,24,31,19,27), +(5,6,9,33,25,33,19,27), +(5,6,10,34,25,34,19,28), +(5,6,11,35,26,35,19,28), +(5,6,12,37,27,36,19,28), +(5,6,13,38,28,38,19,28), +(5,6,14,40,29,39,19,29), +(5,6,15,41,30,40,19,29), +(5,6,16,43,31,42,20,29), +(5,6,17,44,32,43,20,30), +(5,6,18,46,33,44,20,30), +(5,6,19,47,34,46,20,31), +(5,6,20,49,34,47,20,31), +(5,6,21,50,35,49,20,31), +(5,6,22,52,36,50,20,32), +(5,6,23,53,37,51,21,32), +(5,6,24,55,38,53,21,32), +(5,6,25,57,39,54,21,33), +(5,6,26,58,40,56,21,33), +(5,6,27,60,41,57,21,34), +(5,6,28,62,42,59,21,34), +(5,6,29,63,43,60,21,34), +(5,6,30,65,44,62,22,35), +(5,6,31,67,46,63,22,35), +(5,6,32,68,47,65,22,36), +(5,6,33,70,48,67,22,36), +(5,6,34,72,49,68,22,36), +(5,6,35,74,50,70,23,37), +(5,6,36,75,51,71,23,37), +(5,6,37,77,52,73,23,38), +(5,6,38,79,53,75,23,38), +(5,6,39,81,54,76,23,39), +(5,6,40,83,55,78,24,39), +(5,6,41,84,57,80,24,40), +(5,6,42,86,58,81,24,40), +(5,6,43,88,59,83,24,41), +(5,6,44,90,60,85,24,41), +(5,6,45,92,61,86,25,42), +(5,6,46,94,62,88,25,42), +(5,6,47,96,64,90,25,43), +(5,6,48,98,65,92,25,43), +(5,6,49,100,66,93,25,44), +(5,6,50,102,67,95,26,44), +(5,6,51,103,67,96,26,45), +(5,6,52,104,68,97,26,45), +(5,6,53,105,69,98,26,46), +(5,6,54,106,70,99,27,46), +(5,6,55,107,71,100,27,47), +(5,6,56,110,73,103,27,48), +(5,6,57,112,74,105,27,48), +(5,6,58,114,75,107,28,49), +(5,6,59,119,77,109,28,49), +(5,6,60,122,78,111,28,50), +(5,6,61,124,79,113,28,51), +(5,6,62,127,81,115,28,51), +(5,6,63,129,82,118,29,52), +(5,6,64,136,84,120,29,52), +(5,6,65,137,85,123,29,53), +(5,6,66,138,87,125,29,54), +(5,6,67,141,88,127,30,54), +(5,6,68,143,90,129,30,55), +(5,6,69,146,91,132,30,56), +(5,6,70,149,93,134,30,56), +(5,6,71,152,95,137,31,57), +(5,6,72,154,96,139,31,58), +(5,6,73,157,98,142,31,59), +(5,6,74,158,100,145,31,59), +(5,6,75,159,101,147,32,60), +(5,6,76,162,103,150,32,61), +(5,6,77,167,105,152,32,62), +(5,6,78,173,106,155,32,62), +(5,6,79,174,108,158,33,63), +(5,6,80,174,110,161,33,64), (5,8,1,19,18,21,21,27), (5,8,2,19,18,21,22,28), (5,8,3,19,18,22,24,30), @@ -5996,6 +6636,16 @@ INSERT INTO `player_levelstats` VALUES (5,8,68,31,36,51,144,145), (5,8,69,32,37,51,147,148), (5,8,70,32,37,52,149,150), +(5,8,71,32,37,53,152,153), +(5,8,72,32,38,54,155,156), +(5,8,73,32,38,55,158,159), +(5,8,74,33,39,55,161,161), +(5,8,75,33,39,56,164,164), +(5,8,76,33,39,57,167,167), +(5,8,77,34,40,58,170,170), +(5,8,78,34,40,58,173,173), +(5,8,79,34,41,59,176,176), +(5,8,80,35,41,60,179,179), (5,9,1,19,18,22,20,27), (5,9,2,19,18,23,21,28), (5,9,3,20,19,23,22,29), @@ -6066,6 +6716,16 @@ INSERT INTO `player_levelstats` VALUES (5,9,68,49,55,75,127,132), (5,9,69,49,55,76,129,134), (5,9,70,50,56,77,131,136), +(5,9,71,51,57,86,135,147), +(5,9,72,52,57,88,136,149), +(5,9,73,53,58,89,138,152), +(5,9,74,53,59,90,141,155), +(5,9,75,54,60,92,143,157), +(5,9,76,55,61,93,146,160), +(5,9,77,56,62,94,149,163), +(5,9,78,56,63,96,151,166), +(5,9,79,57,64,97,154,169), +(5,9,80,58,65,99,157,171), (6,1,1,28,15,24,15,22), (6,1,2,29,16,25,15,22), (6,1,3,31,17,26,15,23), @@ -6136,6 +6796,16 @@ INSERT INTO `player_levelstats` VALUES (6,1,68,145,88,131,27,52), (6,1,69,148,90,133,28,52), (6,1,70,150,91,135,28,53), +(6,1,71,153,92,137,28,54), +(6,1,72,155,94,140,28,55), +(6,1,73,158,96,142,28,56), +(6,1,74,161,97,145,29,56), +(6,1,75,164,99,147,29,57), +(6,1,76,167,101,150,29,58), +(6,1,77,170,103,153,30,59), +(6,1,78,173,104,155,30,59), +(6,1,79,176,106,164,30,60), +(6,1,80,179,108,170,31,61), (6,3,1,25,18,23,15,23), (6,3,2,25,19,24,16,24), (6,3,3,26,21,25,16,24), @@ -6206,6 +6876,96 @@ INSERT INTO `player_levelstats` VALUES (6,3,68,67,141,107,70,83), (6,3,69,68,144,108,71,84), (6,3,70,69,146,110,72,85), +(6,3,71,70,149,112,73,86), +(6,3,72,71,152,114,74,87), +(6,3,73,72,155,116,75,89), +(6,3,74,73,158,118,77,90), +(6,3,75,74,161,120,78,92), +(6,3,76,75,164,122,79,93), +(6,3,77,76,167,124,81,95), +(6,3,78,77,176,126,85,96), +(6,3,79,78,179,128,86,98), +(6,3,80,79,183,130,88,99), +(6,6,1,28,15,24,15,22), +(6,6,2,29,16,25,15,22), +(6,6,3,31,17,26,15,23), +(6,6,4,32,17,27,15,23), +(6,6,5,33,18,29,15,23), +(6,6,6,34,19,30,15,23), +(6,6,7,36,20,31,16,24), +(6,6,8,37,21,32,16,24), +(6,6,9,38,22,34,16,24), +(6,6,10,40,22,35,16,25), +(6,6,11,41,23,36,16,25), +(6,6,12,43,24,37,16,25), +(6,6,13,44,25,39,16,26), +(6,6,14,46,26,40,16,26), +(6,6,15,47,27,41,17,26), +(6,6,16,48,28,43,17,27), +(6,6,17,50,29,44,17,27), +(6,6,18,51,30,45,17,27), +(6,6,19,53,31,47,17,28), +(6,6,20,54,32,48,17,28), +(6,6,21,56,33,50,17,28), +(6,6,22,58,34,51,18,29), +(6,6,23,59,35,52,18,29), +(6,6,24,61,36,54,18,30), +(6,6,25,62,37,55,18,30), +(6,6,26,64,38,57,18,30), +(6,6,27,66,39,58,18,31), +(6,6,28,67,40,60,18,31), +(6,6,29,69,41,61,19,32), +(6,6,30,71,42,63,19,32), +(6,6,31,72,43,64,19,32), +(6,6,32,74,44,66,19,33), +(6,6,33,76,45,67,19,33), +(6,6,34,77,46,69,20,34), +(6,6,35,79,47,71,20,34), +(6,6,36,81,48,72,20,35), +(6,6,37,83,49,74,20,35), +(6,6,38,85,50,76,20,35), +(6,6,39,86,51,77,21,36), +(6,6,40,88,53,79,21,36), +(6,6,41,90,54,81,21,37), +(6,6,42,92,55,82,21,37), +(6,6,43,94,56,84,21,38), +(6,6,44,96,57,86,22,38), +(6,6,45,98,58,87,22,39), +(6,6,46,99,60,89,22,39), +(6,6,47,101,60,91,22,40), +(6,6,48,103,61,93,22,40), +(6,6,49,105,62,94,23,41), +(6,6,50,107,63,96,23,41), +(6,6,51,109,64,97,23,42), +(6,6,52,110,65,98,23,42), +(6,6,53,111,66,99,24,43), +(6,6,54,112,67,100,24,44), +(6,6,55,113,68,101,24,44), +(6,6,56,116,70,104,24,45), +(6,6,57,121,71,106,24,45), +(6,6,58,123,72,108,25,46), +(6,6,59,123,74,110,25,46), +(6,6,60,125,75,112,25,47), +(6,6,61,127,76,114,25,48), +(6,6,62,133,78,116,25,48), +(6,6,63,135,79,119,26,49), +(6,6,64,139,81,121,26,49), +(6,6,65,142,82,123,26,50), +(6,6,66,146,84,126,26,51), +(6,6,67,150,85,132,27,51), +(6,6,68,153,87,137,27,52), +(6,6,69,157,88,140,27,53), +(6,6,70,160,90,143,27,53), +(6,6,71,163,92,146,28,54), +(6,6,72,165,93,148,28,55), +(6,6,73,167,95,150,28,56), +(6,6,74,171,97,153,28,56), +(6,6,75,174,98,156,29,57), +(6,6,76,178,100,156,29,58), +(6,6,77,179,102,156,29,59), +(6,6,78,179,103,156,29,59), +(6,6,79,182,105,159,30,60), +(6,6,80,185,107,162,30,61), (6,7,1,26,15,23,16,24), (6,7,2,27,15,24,17,25), (6,7,3,28,16,25,18,26), @@ -6276,6 +7036,16 @@ INSERT INTO `player_levelstats` VALUES (6,7,68,104,57,113,100,118), (6,7,69,105,58,114,101,120), (6,7,70,107,59,116,103,122), +(6,7,71,108,60,118,113,124), +(6,7,72,110,61,120,117,127), +(6,7,73,112,62,122,119,129), +(6,7,74,114,63,125,122,131), +(6,7,75,116,64,127,124,133), +(6,7,76,118,65,129,126,136), +(6,7,77,119,66,131,128,138), +(6,7,78,121,67,133,130,140), +(6,7,79,123,68,136,133,143), +(6,7,80,125,69,138,135,145), (6,11,1,26,15,22,17,24), (6,11,2,27,16,23,18,25), (6,11,3,27,16,23,19,26), @@ -6346,6 +7116,16 @@ INSERT INTO `player_levelstats` VALUES (6,11,68,79,63,83,111,131), (6,11,69,80,64,84,113,133), (6,11,70,81,65,85,115,135), +(6,11,71,83,66,86,117,137), +(6,11,72,84,68,88,120,140), +(6,11,73,85,69,89,122,142), +(6,11,74,86,70,91,124,145), +(6,11,75,88,71,92,126,147), +(6,11,76,89,72,94,128,150), +(6,11,77,90,73,95,131,153), +(6,11,78,92,75,97,133,155), +(6,11,79,93,76,98,136,158), +(6,11,80,94,77,100,138,185), (7,1,1,18,23,21,24,20), (7,1,2,19,24,22,24,20), (7,1,3,21,25,23,24,21), @@ -6416,6 +7196,16 @@ INSERT INTO `player_levelstats` VALUES (7,1,68,136,96,128,36,50), (7,1,69,138,98,130,37,50), (7,1,70,140,99,132,37,51), +(7,1,71,143,100,134,37,52), +(7,1,72,145,102,137,37,53), +(7,1,73,148,104,139,37,54), +(7,1,74,151,105,142,38,54), +(7,1,75,154,107,144,38,55), +(7,1,76,157,109,147,38,56), +(7,1,77,163,111,153,39,57), +(7,1,78,169,112,158,39,57), +(7,1,79,172,114,161,39,58), +(7,1,80,175,116,164,40,59), (7,4,1,16,26,20,24,20), (7,4,2,17,27,21,24,20), (7,4,3,18,29,21,24,21), @@ -6486,6 +7276,96 @@ INSERT INTO `player_levelstats` VALUES (7,4,68,87,156,85,42,57), (7,4,69,89,158,87,43,57), (7,4,70,90,161,88,43,58), +(7,4,71,92,164,89,44,59), +(7,4,72,94,167,91,45,59), +(7,4,73,95,170,93,45,60), +(7,4,74,97,173,94,46,61), +(7,4,75,99,176,96,46,62), +(7,4,76,100,179,97,46,63), +(7,4,77,102,182,102,47,64), +(7,4,78,104,186,105,47,65), +(7,4,79,106,189,106,48,66), +(7,4,80,108,192,108,48,67), +(7,6,1,18,23,21,24,20), +(7,6,2,19,24,22,24,20), +(7,6,3,21,25,23,24,21), +(7,6,4,22,25,25,24,21), +(7,6,5,23,26,26,24,21), +(7,6,6,25,27,27,24,21), +(7,6,7,26,28,28,24,22), +(7,6,8,27,29,29,25,22), +(7,6,9,29,29,31,25,22), +(7,6,10,30,30,32,25,23), +(7,6,11,32,31,33,25,23), +(7,6,12,33,32,34,25,23), +(7,6,13,34,33,36,25,24), +(7,6,14,36,34,37,25,24), +(7,6,15,37,35,38,25,24), +(7,6,16,39,36,40,25,25), +(7,6,17,40,36,41,25,25), +(7,6,18,42,37,43,26,25), +(7,6,19,43,38,44,26,26), +(7,6,20,45,39,45,26,26), +(7,6,21,47,40,47,26,26), +(7,6,22,48,41,48,26,27), +(7,6,23,50,42,50,26,27), +(7,6,24,51,43,51,26,28), +(7,6,25,53,44,52,27,28), +(7,6,26,55,45,54,27,28), +(7,6,27,56,46,55,27,29), +(7,6,28,58,47,57,27,29), +(7,6,29,59,48,58,27,30), +(7,6,30,61,49,60,27,30), +(7,6,31,63,50,62,27,30), +(7,6,32,65,51,63,28,31), +(7,6,33,66,52,65,28,31), +(7,6,34,68,53,66,28,32), +(7,6,35,70,55,68,28,32), +(7,6,36,72,56,69,28,33), +(7,6,37,73,57,71,29,33), +(7,6,38,75,58,73,29,34), +(7,6,39,77,59,74,29,34), +(7,6,40,79,60,76,29,35), +(7,6,41,81,61,78,29,35), +(7,6,42,82,62,79,30,35), +(7,6,43,84,64,81,30,36), +(7,6,44,86,65,83,30,36), +(7,6,45,88,66,85,30,37), +(7,6,46,90,67,86,30,37), +(7,6,47,92,68,88,31,38), +(7,6,48,94,70,90,31,38), +(7,6,49,96,71,92,31,39), +(7,6,50,98,72,93,31,40), +(7,6,51,99,72,93,32,40), +(7,6,52,100,73,95,32,41), +(7,6,53,101,74,96,32,41), +(7,6,54,102,75,97,32,42), +(7,6,55,103,76,98,33,42), +(7,6,56,106,78,101,33,43), +(7,6,57,111,79,103,33,43), +(7,6,58,113,80,105,34,44), +(7,6,59,116,82,107,34,44), +(7,6,60,118,83,109,34,45), +(7,6,61,120,84,111,34,46), +(7,6,62,127,86,119,34,46), +(7,6,63,129,87,122,35,47), +(7,6,64,132,89,125,35,47), +(7,6,65,135,90,127,35,48), +(7,6,66,137,92,130,35,49), +(7,6,67,138,93,130,36,49), +(7,6,68,140,95,131,36,50), +(7,6,69,142,96,131,36,51), +(7,6,70,145,98,132,36,51), +(7,6,71,148,100,135,37,52), +(7,6,72,150,101,137,37,53), +(7,6,73,153,103,140,37,54), +(7,6,74,154,105,142,37,54), +(7,6,75,155,106,145,38,55), +(7,6,76,158,108,151,38,56), +(7,6,77,161,110,157,38,57), +(7,6,78,164,111,162,38,57), +(7,6,79,167,113,165,39,58), +(7,6,80,170,115,168,39,59), (7,8,1,15,23,19,27,22), (7,8,2,15,23,19,28,23), (7,8,3,15,23,20,30,25), @@ -6556,6 +7436,16 @@ INSERT INTO `player_levelstats` VALUES (7,8,68,27,41,49,150,140), (7,8,69,28,42,49,153,143), (7,8,70,28,42,50,155,145), +(7,8,71,28,42,51,168,148), +(7,8,72,28,43,52,168,151), +(7,8,73,28,43,53,171,154), +(7,8,74,29,44,53,174,156), +(7,8,75,29,44,54,177,159), +(7,8,76,29,44,55,180,162), +(7,8,77,30,45,56,183,165), +(7,8,78,30,45,56,186,168), +(7,8,79,30,46,57,190,171), +(7,8,80,31,46,58,193,174), (7,9,1,15,23,20,26,22), (7,9,2,15,23,21,27,23), (7,9,3,16,24,21,28,24), @@ -6626,6 +7516,16 @@ INSERT INTO `player_levelstats` VALUES (7,9,68,45,59,73,133,127), (7,9,69,45,60,74,135,129), (7,9,70,46,61,75,137,131), +(7,9,71,47,62,84,147,142), +(7,9,72,48,62,85,148,144), +(7,9,73,49,63,85,153,147), +(7,9,74,49,64,88,153,150), +(7,9,75,50,65,90,155,152), +(7,9,76,51,66,91,158,155), +(7,9,77,52,67,92,161,158), +(7,9,78,52,68,93,163,161), +(7,9,79,53,69,95,166,164), +(7,9,80,54,70,96,170,166), (8,1,1,24,22,23,16,21), (8,1,2,25,23,24,16,21), (8,1,3,27,24,25,16,22), @@ -6696,6 +7596,16 @@ INSERT INTO `player_levelstats` VALUES (8,1,68,141,95,130,28,51), (8,1,69,144,97,132,29,51), (8,1,70,146,98,134,29,52), +(8,1,71,149,99,136,29,53), +(8,1,72,151,101,139,29,54), +(8,1,73,154,103,141,29,55), +(8,1,74,157,104,144,30,55), +(8,1,75,166,106,151,30,56), +(8,1,76,172,108,157,30,57), +(8,1,77,175,110,161,31,58), +(8,1,78,179,111,163,31,58), +(8,1,79,182,113,164,31,59), +(8,1,80,185,115,169,32,60), (8,3,1,21,25,22,16,22), (8,3,2,21,26,23,17,23), (8,3,3,22,28,24,17,23), @@ -6766,6 +7676,16 @@ INSERT INTO `player_levelstats` VALUES (8,3,68,63,148,106,71,82), (8,3,69,64,151,107,72,83), (8,3,70,65,153,109,73,84), +(8,3,71,66,156,111,74,85), +(8,3,72,67,159,113,75,86), +(8,3,73,68,162,115,76,88), +(8,3,74,69,165,117,78,89), +(8,3,75,70,174,119,82,91), +(8,3,76,71,177,121,83,92), +(8,3,77,72,180,123,85,94), +(8,3,78,73,184,125,86,95), +(8,3,79,74,187,127,87,97), +(8,3,80,75,190,129,89,98), (8,4,1,22,25,22,16,21), (8,4,2,23,26,23,16,21), (8,4,3,24,28,23,16,22), @@ -6836,6 +7756,16 @@ INSERT INTO `player_levelstats` VALUES (8,4,68,93,155,87,34,58), (8,4,69,95,157,89,35,58), (8,4,70,96,160,90,35,59), +(8,4,71,98,163,94,35,60), +(8,4,72,100,166,96,36,60), +(8,4,73,101,169,96,36,61), +(8,4,74,103,172,97,37,62), +(8,4,75,105,175,98,37,63), +(8,4,76,106,178,99,37,64), +(8,4,77,108,181,105,38,65), +(8,4,78,110,185,107,38,66), +(8,4,79,112,188,109,39,67), +(8,4,80,114,191,110,39,68), (8,5,1,21,22,21,18,24), (8,5,2,21,22,21,19,25), (8,5,3,21,22,22,21,27), @@ -6906,6 +7836,96 @@ INSERT INTO `player_levelstats` VALUES (8,5,68,39,46,58,136,147), (8,5,69,40,46,58,139,150), (8,5,70,40,47,59,141,152), +(8,5,71,40,48,60,144,155), +(8,5,72,41,48,60,147,158), +(8,5,73,41,49,61,150,161), +(8,5,74,42,49,62,152,164), +(8,5,75,42,50,63,155,167), +(8,5,76,42,51,64,158,170), +(8,5,77,43,51,65,161,173), +(8,5,78,43,52,66,164,176), +(8,5,79,44,52,67,167,179), +(8,5,80,44,53,68,170,182), +(8,6,1,24,22,23,16,21), +(8,6,2,25,23,24,16,21), +(8,6,3,27,24,25,16,22), +(8,6,4,28,24,26,16,22), +(8,6,5,29,25,28,16,22), +(8,6,6,31,26,29,16,22), +(8,6,7,32,27,30,17,23), +(8,6,8,33,28,31,17,23), +(8,6,9,35,28,33,17,23), +(8,6,10,36,29,34,17,24), +(8,6,11,37,30,35,17,24), +(8,6,12,39,31,36,17,24), +(8,6,13,40,32,38,17,25), +(8,6,14,42,33,39,17,25), +(8,6,15,43,34,40,18,25), +(8,6,16,45,35,42,18,26), +(8,6,17,46,35,43,18,26), +(8,6,18,48,36,44,18,26), +(8,6,19,49,37,46,18,27), +(8,6,20,51,38,47,18,27), +(8,6,21,52,39,49,18,27), +(8,6,22,54,40,50,18,28), +(8,6,23,55,41,51,19,28), +(8,6,24,57,42,53,19,29), +(8,6,25,59,43,54,19,29), +(8,6,26,60,44,56,19,29), +(8,6,27,62,45,57,19,30), +(8,6,28,63,46,59,19,30), +(8,6,29,65,47,60,20,31), +(8,6,30,67,48,62,20,31), +(8,6,31,69,49,63,20,31), +(8,6,32,70,50,65,20,32), +(8,6,33,72,51,67,20,32), +(8,6,34,74,53,68,20,33), +(8,6,35,75,54,70,21,33), +(8,6,36,77,55,71,21,34), +(8,6,37,79,56,73,21,34), +(8,6,38,81,57,75,21,35), +(8,6,39,83,58,76,21,35), +(8,6,40,84,59,78,22,35), +(8,6,41,86,60,80,22,36), +(8,6,42,88,62,81,22,36), +(8,6,43,90,63,83,22,37), +(8,6,44,92,64,85,22,37), +(8,6,45,94,65,86,23,38), +(8,6,46,96,66,88,23,38), +(8,6,47,98,67,90,23,39), +(8,6,48,100,69,92,23,39), +(8,6,49,102,70,93,24,40), +(8,6,50,103,71,95,24,40), +(8,6,51,105,72,96,24,41), +(8,6,52,106,74,97,24,42), +(8,6,53,107,73,98,25,42), +(8,6,54,108,74,99,25,43), +(8,6,55,109,75,100,25,43), +(8,6,56,112,77,103,25,44), +(8,6,57,114,78,105,25,44), +(8,6,58,118,79,107,26,45), +(8,6,59,119,81,109,26,45), +(8,6,60,121,82,111,26,46), +(8,6,61,123,83,113,26,47), +(8,6,62,126,85,115,26,47), +(8,6,63,128,86,118,27,48), +(8,6,64,131,88,120,27,48), +(8,6,65,138,89,122,27,49), +(8,6,66,140,91,125,27,50), +(8,6,67,143,92,127,28,50), +(8,6,68,145,94,129,28,51), +(8,6,69,148,95,132,28,52), +(8,6,70,151,97,134,28,52), +(8,6,71,154,99,137,29,53), +(8,6,72,156,100,139,29,54), +(8,6,73,159,102,142,29,55), +(8,6,74,162,104,144,29,55), +(8,6,75,165,105,147,30,56), +(8,6,76,168,107,150,30,57), +(8,6,77,169,109,153,30,58), +(8,6,78,170,110,155,30,58), +(8,6,79,178,112,158,31,59), +(8,6,80,181,114,161,31,60), (8,7,1,22,22,22,17,23), (8,7,2,23,22,23,18,24), (8,7,3,24,23,24,19,25), @@ -6976,6 +7996,16 @@ INSERT INTO `player_levelstats` VALUES (8,7,68,100,64,112,101,117), (8,7,69,101,65,113,102,119), (8,7,70,103,66,115,104,121), +(8,7,71,104,67,117,116,123), +(8,7,72,106,68,119,118,126), +(8,7,73,108,69,121,121,128), +(8,7,74,110,70,124,123,130), +(8,7,75,112,71,126,125,132), +(8,7,76,114,72,128,127,135), +(8,7,77,115,73,130,129,137), +(8,7,78,117,74,132,132,139), +(8,7,79,119,75,135,134,142), +(8,7,80,121,76,137,136,144), (8,8,1,21,22,21,19,23), (8,8,2,21,22,21,20,24), (8,8,3,21,22,22,22,26), @@ -7046,6 +8076,16 @@ INSERT INTO `player_levelstats` VALUES (8,8,68,33,40,51,142,141), (8,8,69,34,41,51,145,144), (8,8,70,34,41,52,147,146), +(8,8,71,34,41,53,150,149), +(8,8,72,34,42,54,153,152), +(8,8,73,34,42,55,156,155), +(8,8,74,35,43,55,159,157), +(8,8,75,35,43,56,162,160), +(8,8,76,35,43,57,168,163), +(8,8,77,36,44,58,168,166), +(8,8,78,36,44,58,171,169), +(8,8,79,36,45,59,177,172), +(8,8,80,37,45,60,177,175), (10,2,1,19,22,21,24,20), (10,2,2,20,23,22,25,21), (10,2,3,21,23,23,25,21), @@ -7116,6 +8156,16 @@ INSERT INTO `player_levelstats` VALUES (10,2,68,119,77,115,85,85), (10,2,69,121,78,117,86,87), (10,2,70,123,79,119,87,88), +(10,2,71,125,80,120,88,89), +(10,2,72,128,81,123,90,91), +(10,2,73,130,82,125,91,93), +(10,2,74,133,84,127,93,94), +(10,2,75,135,85,129,94,96), +(10,2,76,137,86,132,96,97), +(10,2,77,140,88,134,97,99), +(10,2,78,143,89,136,99,101), +(10,2,79,145,90,139,100,102), +(10,2,80,148,92,141,102,104), (10,3,1,17,25,20,24,20), (10,3,2,17,26,21,25,21), (10,3,3,18,28,22,25,21), @@ -7186,6 +8236,16 @@ INSERT INTO `player_levelstats` VALUES (10,3,68,59,148,104,79,80), (10,3,69,60,151,105,80,81), (10,3,70,61,153,107,81,82), +(10,3,71,62,156,108,82,83), +(10,3,72,63,159,110,83,84), +(10,3,73,64,162,112,84,86), +(10,3,74,65,165,114,86,87), +(10,3,75,66,168,116,87,89), +(10,3,76,67,171,118,89,90), +(10,3,77,68,174,120,90,92), +(10,3,78,69,177,122,91,93), +(10,3,79,70,180,124,92,95), +(10,3,80,71,183,126,94,96), (10,4,1,18,25,20,24,19), (10,4,2,19,26,21,24,19), (10,4,3,20,28,21,24,20), @@ -7256,6 +8316,16 @@ INSERT INTO `player_levelstats` VALUES (10,4,68,89,155,85,42,56), (10,4,69,91,157,87,43,56), (10,4,70,92,160,88,43,57), +(10,4,71,94,163,88,43,58), +(10,4,72,96,166,90,44,58), +(10,4,73,97,169,92,44,59), +(10,4,74,99,172,93,45,60), +(10,4,75,101,175,95,45,61), +(10,4,76,102,178,96,45,62), +(10,4,77,104,181,101,46,63), +(10,4,78,106,185,104,46,64), +(10,4,79,108,188,105,47,65), +(10,4,80,110,191,107,47,66), (10,5,1,17,22,19,26,22), (10,5,2,17,22,19,27,23), (10,5,3,17,22,20,29,25), @@ -7326,6 +8396,96 @@ INSERT INTO `player_levelstats` VALUES (10,5,68,35,46,56,144,145), (10,5,69,36,46,56,147,148), (10,5,70,36,47,57,149,150), +(10,5,71,36,48,57,152,153), +(10,5,72,37,48,57,155,156), +(10,5,73,37,49,58,158,159), +(10,5,74,38,49,59,160,163), +(10,5,75,38,50,60,163,165), +(10,5,76,38,51,61,166,170), +(10,5,77,39,51,62,168,175), +(10,5,78,39,52,63,172,174), +(10,5,79,40,52,64,175,177), +(10,5,80,40,53,65,178,180), +(10,6,1,18,23,21,24,20), +(10,6,2,19,24,22,24,20), +(10,6,3,21,25,23,24,21), +(10,6,4,22,25,25,24,21), +(10,6,5,23,26,26,24,21), +(10,6,6,25,27,27,24,21), +(10,6,7,26,28,28,24,22), +(10,6,8,27,29,29,25,22), +(10,6,9,29,29,31,25,22), +(10,6,10,30,30,32,25,23), +(10,6,11,32,31,33,25,23), +(10,6,12,33,32,34,25,23), +(10,6,13,34,33,36,25,24), +(10,6,14,36,34,37,25,24), +(10,6,15,37,35,38,25,24), +(10,6,16,39,36,40,25,25), +(10,6,17,40,36,41,25,25), +(10,6,18,42,37,43,26,25), +(10,6,19,43,38,44,26,26), +(10,6,20,45,39,45,26,26), +(10,6,21,47,40,47,26,26), +(10,6,22,48,41,48,26,27), +(10,6,23,50,42,50,26,27), +(10,6,24,51,43,51,26,28), +(10,6,25,53,44,52,27,28), +(10,6,26,55,45,54,27,28), +(10,6,27,56,46,55,27,29), +(10,6,28,58,47,57,27,29), +(10,6,29,59,48,58,27,30), +(10,6,30,61,49,60,27,30), +(10,6,31,63,50,62,27,30), +(10,6,32,65,51,63,28,31), +(10,6,33,66,52,65,28,31), +(10,6,34,68,53,66,28,32), +(10,6,35,70,55,68,28,32), +(10,6,36,72,56,69,28,33), +(10,6,37,73,57,71,29,33), +(10,6,38,75,58,73,29,34), +(10,6,39,77,59,74,29,34), +(10,6,40,79,60,76,29,35), +(10,6,41,81,61,78,29,35), +(10,6,42,82,62,79,30,35), +(10,6,43,84,64,81,30,36), +(10,6,44,86,65,83,30,36), +(10,6,45,88,66,85,30,37), +(10,6,46,90,67,86,30,37), +(10,6,47,92,68,88,31,38), +(10,6,48,94,69,90,31,38), +(10,6,49,96,69,92,31,39), +(10,6,50,98,70,93,31,40), +(10,6,51,100,71,95,32,40), +(10,6,52,102,72,96,32,41), +(10,6,53,103,73,97,32,41), +(10,6,54,104,74,98,32,41), +(10,6,55,105,75,97,33,41), +(10,6,56,108,77,100,33,42), +(10,6,57,113,78,102,33,42), +(10,6,58,115,79,104,34,43), +(10,6,59,117,81,106,34,43), +(10,6,60,118,82,108,34,44), +(10,6,61,119,83,110,34,45), +(10,6,62,121,85,112,34,45), +(10,6,63,124,86,115,35,46), +(10,6,64,127,88,117,35,46), +(10,6,65,133,89,119,35,47), +(10,6,66,135,91,122,35,48), +(10,6,67,139,92,124,36,48), +(10,6,68,141,94,126,36,49), +(10,6,69,142,95,129,36,50), +(10,6,70,145,97,131,36,50), +(10,6,71,150,99,134,37,51), +(10,6,72,152,100,136,37,52), +(10,6,73,155,102,139,37,53), +(10,6,74,158,104,141,37,53), +(10,6,75,159,105,144,38,54), +(10,6,76,160,107,147,38,55), +(10,6,77,163,109,149,38,56), +(10,6,78,166,110,152,38,56), +(10,6,79,169,112,155,39,57), +(10,6,80,172,114,158,39,58), (10,8,1,17,22,19,27,21), (10,8,2,17,22,19,28,22), (10,8,3,17,22,20,30,24), @@ -7396,6 +8556,16 @@ INSERT INTO `player_levelstats` VALUES (10,8,68,29,40,49,150,139), (10,8,69,30,41,49,153,142), (10,8,70,30,41,50,155,144), +(10,8,71,30,41,50,158,147), +(10,8,72,30,42,51,161,150), +(10,8,73,30,42,52,164,153), +(10,8,74,31,43,52,167,155), +(10,8,75,31,43,53,170,158), +(10,8,76,31,43,54,173,161), +(10,8,77,32,44,55,176,164), +(10,8,78,32,44,55,179,167), +(10,8,79,32,45,56,182,170), +(10,8,80,33,45,57,185,173), (10,9,1,17,22,20,26,21), (10,9,2,17,22,21,27,22), (10,9,3,18,23,21,28,23), @@ -7466,6 +8636,16 @@ INSERT INTO `player_levelstats` VALUES (10,9,68,47,58,73,133,126), (10,9,69,47,59,74,135,128), (10,9,70,48,60,75,137,130), +(10,9,71,49,61,83,139,141), +(10,9,72,50,61,84,142,143), +(10,9,73,51,62,84,144,146), +(10,9,74,51,63,86,147,149), +(10,9,75,52,64,89,149,151), +(10,9,76,53,65,90,155,154), +(10,9,77,54,66,91,155,157), +(10,9,78,54,67,93,157,160), +(10,9,79,55,68,94,160,163), +(10,9,80,56,69,95,163,165), (11,1,1,24,17,21,21,22), (11,1,2,25,18,22,21,22), (11,1,3,27,19,23,21,23), @@ -7536,6 +8716,16 @@ INSERT INTO `player_levelstats` VALUES (11,1,68,141,90,128,33,52), (11,1,69,144,92,130,34,52), (11,1,70,146,93,132,34,53), +(11,1,71,149,94,134,34,54), +(11,1,72,151,96,137,34,55), +(11,1,73,154,98,139,34,56), +(11,1,74,157,99,142,35,56), +(11,1,75,166,101,149,35,57), +(11,1,76,172,103,155,35,58), +(11,1,77,175,105,159,36,59), +(11,1,78,179,106,161,36,59), +(11,1,79,182,108,164,36,60), +(11,1,80,185,110,167,37,61), (11,2,1,23,17,21,21,23), (11,2,2,24,18,22,22,24), (11,2,3,25,18,23,22,24), @@ -7606,6 +8796,16 @@ INSERT INTO `player_levelstats` VALUES (11,2,68,123,72,115,82,88), (11,2,69,125,73,117,83,90), (11,2,70,127,74,119,84,91), +(11,2,71,130,75,121,87,92), +(11,2,72,132,76,124,90,94), +(11,2,73,134,77,126,93,96), +(11,2,74,137,79,128,97,97), +(11,2,75,139,80,130,101,99), +(11,2,76,142,81,133,106,100), +(11,2,77,144,83,135,108,102), +(11,2,78,147,84,137,110,104), +(11,2,79,149,85,140,111,105), +(11,2,80,152,87,142,113,107), (11,3,1,21,20,20,21,23), (11,3,2,21,21,21,22,24), (11,3,3,22,23,22,22,24), @@ -7676,6 +8876,16 @@ INSERT INTO `player_levelstats` VALUES (11,3,68,63,143,104,76,83), (11,3,69,64,146,105,77,84), (11,3,70,65,148,107,78,85), +(11,3,71,66,151,109,79,86), +(11,3,72,67,154,111,80,87), +(11,3,73,68,157,113,81,89), +(11,3,74,69,160,115,83,90), +(11,3,75,70,163,117,84,92), +(11,3,76,71,166,119,85,93), +(11,3,77,72,169,121,87,95), +(11,3,78,73,172,123,88,96), +(11,3,79,74,175,125,89,98), +(11,3,80,75,178,127,91,99), (11,5,1,21,17,19,23,25), (11,5,2,21,17,19,24,26), (11,5,3,21,17,20,26,28), @@ -7746,6 +8956,96 @@ INSERT INTO `player_levelstats` VALUES (11,5,68,39,41,56,141,148), (11,5,69,40,41,56,144,151), (11,5,70,40,42,57,146,153), +(11,5,71,40,43,58,149,156), +(11,5,72,41,43,58,155,159), +(11,5,73,41,44,59,157,160), +(11,5,74,42,44,61,160,163), +(11,5,75,42,45,62,164,166), +(11,5,76,42,46,62,167,169), +(11,5,77,43,46,63,168,172), +(11,5,78,43,47,64,169,177), +(11,5,79,44,47,65,172,180), +(11,5,80,44,48,66,175,183), +(11,6,1,24,17,21,21,22), +(11,6,2,25,18,22,21,22), +(11,6,3,27,19,23,21,23), +(11,6,4,28,19,25,21,23), +(11,6,5,29,20,26,21,23), +(11,6,6,31,21,27,21,23), +(11,6,7,32,22,28,21,24), +(11,6,8,33,23,29,22,24), +(11,6,9,35,24,31,22,24), +(11,6,10,36,24,32,22,25), +(11,6,11,37,25,33,22,25), +(11,6,12,39,26,34,22,25), +(11,6,13,40,27,36,22,26), +(11,6,14,42,28,37,22,26), +(11,6,15,43,29,38,22,26), +(11,6,16,45,30,40,22,27), +(11,6,17,46,31,41,23,27), +(11,6,18,48,32,43,23,27), +(11,6,19,49,33,44,23,28), +(11,6,20,51,34,45,23,28), +(11,6,21,52,34,47,23,28), +(11,6,22,54,35,48,23,29), +(11,6,23,55,36,50,23,29), +(11,6,24,57,37,51,24,30), +(11,6,25,59,38,52,24,30), +(11,6,26,60,39,54,24,30), +(11,6,27,62,40,55,24,31), +(11,6,28,63,41,57,24,31), +(11,6,29,65,43,58,24,32), +(11,6,30,67,44,60,24,32), +(11,6,31,69,45,62,25,32), +(11,6,32,70,46,63,25,33), +(11,6,33,72,47,65,25,33), +(11,6,34,74,48,66,25,34), +(11,6,35,75,49,68,25,34), +(11,6,36,77,50,69,26,35), +(11,6,37,79,51,71,26,35), +(11,6,38,81,52,73,26,35), +(11,6,39,83,53,74,26,36), +(11,6,40,84,55,76,26,36), +(11,6,41,86,56,78,27,37), +(11,6,42,88,57,79,27,37), +(11,6,43,90,58,81,27,38), +(11,6,44,92,59,83,27,38), +(11,6,45,94,60,85,27,39), +(11,6,46,96,62,86,28,39), +(11,6,47,98,63,88,28,40), +(11,6,48,100,64,90,28,40), +(11,6,49,102,65,92,28,41), +(11,6,50,103,65,93,29,41), +(11,6,51,105,66,94,29,42), +(11,6,52,106,67,95,29,42), +(11,6,53,107,68,96,29,43), +(11,6,54,108,69,97,30,44), +(11,6,55,109,70,98,30,44), +(11,6,56,112,72,101,30,45), +(11,6,57,114,73,103,30,45), +(11,6,58,117,74,105,31,46), +(11,6,59,119,76,107,31,46), +(11,6,60,121,77,109,31,47), +(11,6,61,123,78,111,31,48), +(11,6,62,126,80,113,31,48), +(11,6,63,128,81,116,32,49), +(11,6,64,131,83,118,32,49), +(11,6,65,136,84,120,32,50), +(11,6,66,140,86,123,32,51), +(11,6,67,141,87,125,33,51), +(11,6,68,141,89,127,33,52), +(11,6,69,144,90,130,33,53), +(11,6,70,147,92,132,33,53), +(11,6,71,150,94,135,34,54), +(11,6,72,152,95,137,34,55), +(11,6,73,155,97,140,34,56), +(11,6,74,162,99,142,34,56), +(11,6,75,165,100,145,35,57), +(11,6,76,167,102,146,35,58), +(11,6,77,169,104,150,35,59), +(11,6,78,170,105,152,35,59), +(11,6,79,173,107,156,36,60), +(11,6,80,176,109,159,36,61), (11,7,1,22,17,20,22,24), (11,7,2,23,17,21,23,25), (11,7,3,24,18,22,24,26), @@ -7816,6 +9116,16 @@ INSERT INTO `player_levelstats` VALUES (11,7,68,100,59,110,106,118), (11,7,69,101,60,111,107,120), (11,7,70,103,61,113,109,122), +(11,7,71,104,62,115,122,124), +(11,7,72,106,63,117,124,127), +(11,7,73,108,64,119,126,129), +(11,7,74,110,65,122,128,131), +(11,7,75,112,66,124,130,133), +(11,7,76,114,67,126,133,136), +(11,7,77,115,68,128,135,138), +(11,7,78,117,69,130,137,140), +(11,7,79,119,70,133,139,143), +(11,7,80,121,71,135,141,145), (11,8,1,21,17,19,24,24), (11,8,2,21,17,19,25,25), (11,8,3,21,17,20,27,27), @@ -7885,7 +9195,17 @@ INSERT INTO `player_levelstats` VALUES (11,8,67,33,35,48,145,140), (11,8,68,33,35,49,147,142), (11,8,69,34,36,49,150,145), -(11,8,70,34,36,50,152,147); +(11,8,70,34,36,50,152,147), +(11,8,71,34,36,51,155,150), +(11,8,72,34,37,52,161,153), +(11,8,73,34,37,53,161,156), +(11,8,74,35,38,53,164,158), +(11,8,75,35,38,54,167,161), +(11,8,76,35,38,55,170,164), +(11,8,77,36,39,56,173,167), +(11,8,78,36,39,56,176,170), +(11,8,79,36,40,57,179,173), +(11,8,80,37,40,58,182,176); /*!40000 ALTER TABLE `player_levelstats` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/wotlk_updates/12_mangos_player_levelstats.sql b/sql/wotlk_updates/12_mangos_player_levelstats.sql new file mode 100644 index 000000000..4d8885c83 --- /dev/null +++ b/sql/wotlk_updates/12_mangos_player_levelstats.sql @@ -0,0 +1,5023 @@ +DELETE FROM `player_levelstats`; +INSERT INTO `player_levelstats` VALUES +(1,1,1,23,20,22,20,20), +(1,1,2,24,21,23,20,20), +(1,1,3,26,22,24,20,21), +(1,1,4,27,22,26,20,21), +(1,1,5,28,23,27,20,21), +(1,1,6,30,24,28,20,21), +(1,1,7,31,25,29,21,22), +(1,1,8,32,26,30,21,22), +(1,1,9,34,26,32,21,22), +(1,1,10,35,27,33,21,23), +(1,1,11,36,28,34,21,23), +(1,1,12,38,29,35,21,23), +(1,1,13,39,30,37,21,24), +(1,1,14,41,31,38,21,24), +(1,1,15,42,32,39,21,24), +(1,1,16,44,33,41,21,25), +(1,1,17,45,34,42,22,25), +(1,1,18,47,34,43,22,25), +(1,1,19,48,35,45,22,26), +(1,1,20,50,36,46,22,26), +(1,1,21,51,37,48,22,26), +(1,1,22,53,38,49,22,27), +(1,1,23,54,39,51,22,27), +(1,1,24,56,40,52,23,28), +(1,1,25,58,41,53,23,28), +(1,1,26,59,42,55,23,28), +(1,1,27,61,43,56,23,29), +(1,1,28,63,44,58,23,29), +(1,1,29,64,45,59,23,30), +(1,1,30,66,46,61,24,30), +(1,1,31,68,47,62,24,30), +(1,1,32,69,48,64,24,31), +(1,1,33,71,50,66,24,31), +(1,1,34,73,51,67,24,32), +(1,1,35,74,52,69,24,32), +(1,1,36,76,53,70,25,33), +(1,1,37,78,54,72,25,33), +(1,1,38,80,55,74,25,34), +(1,1,39,82,56,75,25,34), +(1,1,40,83,57,77,25,35), +(1,1,41,85,58,79,26,35), +(1,1,42,87,60,80,26,35), +(1,1,43,89,61,82,26,36), +(1,1,44,91,62,84,26,36), +(1,1,45,93,63,85,26,37), +(1,1,46,95,64,87,27,37), +(1,1,47,97,66,89,27,38), +(1,1,48,99,67,91,27,38), +(1,1,49,101,68,93,27,39), +(1,1,50,103,69,94,28,40), +(1,1,51,105,71,96,28,40), +(1,1,52,107,72,98,28,41), +(1,1,53,109,73,100,28,41), +(1,1,54,111,74,102,29,42), +(1,1,55,113,76,103,29,42), +(1,1,56,115,77,105,29,43), +(1,1,57,117,78,107,29,43), +(1,1,58,119,79,109,30,44), +(1,1,59,121,81,111,30,44), +(1,1,60,123,82,113,30,45), +(1,1,61,125,83,115,30,46), +(1,1,62,127,85,117,31,46), +(1,1,63,129,86,119,31,47), +(1,1,64,132,88,121,31,47), +(1,1,65,134,89,123,32,48), +(1,1,66,136,90,125,32,49), +(1,1,67,138,92,127,32,49), +(1,1,68,140,93,129,32,50), +(1,1,69,143,95,131,33,50), +(1,1,70,145,96,133,33,51), +(1,1,71,148,97,140,33,53), +(1,1,72,156,99,143,33,54), +(1,1,73,162,101,148,33,55), +(1,1,74,162,102,148,34,55), +(1,1,75,165,104,150,34,56), +(1,1,76,171,106,156,34,57), +(1,1,77,171,108,157,35,58), +(1,1,78,174,109,159,35,58), +(1,1,79,181,111,165,35,59), +(1,1,80,184,113,168,36,60), + +(1,2,1,22,20,22,20,21), +(1,2,2,23,21,23,21,22), +(1,2,3,24,21,24,21,22), +(1,2,4,25,22,25,22,23), +(1,2,5,26,22,26,23,24), +(1,2,6,28,23,27,23,25), +(1,2,7,29,24,28,24,25), +(1,2,8,30,24,29,25,26), +(1,2,9,31,25,30,25,27), +(1,2,10,32,25,32,26,27), +(1,2,11,33,26,33,27,28), +(1,2,12,35,27,34,27,29), +(1,2,13,36,27,35,28,30), +(1,2,14,37,28,36,29,31), +(1,2,15,38,29,37,30,31), +(1,2,16,40,29,38,30,32), +(1,2,17,41,30,40,31,33), +(1,2,18,42,31,41,32,34), +(1,2,19,43,31,42,33,35), +(1,2,20,45,32,43,33,35), +(1,2,21,46,33,45,34,36), +(1,2,22,47,33,46,35,37), +(1,2,23,49,34,47,36,38), +(1,2,24,50,35,48,37,39), +(1,2,25,51,36,50,37,40), +(1,2,26,53,36,51,38,41), +(1,2,27,54,37,52,39,42), +(1,2,28,56,38,54,40,43), +(1,2,29,57,39,55,41,43), +(1,2,30,58,39,56,42,44), +(1,2,31,60,40,58,43,45), +(1,2,32,61,41,59,43,46), +(1,2,33,63,42,60,44,47), +(1,2,34,64,43,62,45,48), +(1,2,35,66,44,63,46,49), +(1,2,36,67,44,65,47,50), +(1,2,37,69,45,66,48,51), +(1,2,38,70,46,67,49,52), +(1,2,39,72,47,69,50,53), +(1,2,40,73,48,70,51,54), +(1,2,41,75,49,72,52,55), +(1,2,42,77,49,73,53,56), +(1,2,43,78,50,75,54,57), +(1,2,44,80,51,76,55,58), +(1,2,45,81,52,78,56,59), +(1,2,46,83,53,79,57,61), +(1,2,47,85,54,81,58,62), +(1,2,48,86,55,83,59,63), +(1,2,49,88,56,84,60,64), +(1,2,50,90,57,86,61,65), +(1,2,51,91,58,87,62,66), +(1,2,52,93,59,89,63,67), +(1,2,53,95,60,91,64,68), +(1,2,54,97,61,92,65,69), +(1,2,55,98,61,94,66,71), +(1,2,56,100,62,95,67,72), +(1,2,57,102,63,97,68,73), +(1,2,58,104,64,99,69,74), +(1,2,59,105,65,101,70,75), +(1,2,60,107,66,102,71,77), +(1,2,61,109,67,104,73,78), +(1,2,62,111,69,106,74,79), +(1,2,63,113,70,107,75,80), +(1,2,64,115,71,109,76,81), +(1,2,65,116,72,111,77,83), +(1,2,66,118,73,113,78,84), +(1,2,67,120,74,115,79,85), +(1,2,68,122,75,116,81,86), +(1,2,69,124,76,118,82,88), +(1,2,70,126,77,120,83,89), +(1,2,71,148,78,122,84,92), +(1,2,72,150,79,125,86,94), +(1,2,73,152,80,127,87,96), +(1,2,74,156,82,129,89,97), +(1,2,75,158,83,131,90,99), +(1,2,76,162,84,134,92,100), +(1,2,77,164,86,136,93,103), +(1,2,78,167,87,138,95,105), +(1,2,79,170,88,153,96,106), +(1,2,80,173,90,160,98,108), + +(1,4,1,21,23,21,20,20), +(1,4,2,22,24,22,20,20), +(1,4,3,23,26,22,20,21), +(1,4,4,23,27,23,20,21), +(1,4,5,24,29,24,21,21), +(1,4,6,25,30,25,21,22), +(1,4,7,26,32,25,21,22), +(1,4,8,26,33,26,21,23), +(1,4,9,27,35,27,21,23), +(1,4,10,28,36,27,21,23), +(1,4,11,29,38,28,22,24), +(1,4,12,30,39,29,22,24), +(1,4,13,31,41,30,22,25), +(1,4,14,31,43,31,22,25), +(1,4,15,32,44,31,22,25), +(1,4,16,33,46,32,23,26), +(1,4,17,34,48,33,23,26), +(1,4,18,35,49,34,23,27), +(1,4,19,36,51,35,23,27), +(1,4,20,37,53,35,23,28), +(1,4,21,38,54,36,24,28), +(1,4,22,39,56,37,24,29), +(1,4,23,40,58,38,24,29), +(1,4,24,41,60,39,24,30), +(1,4,25,42,61,40,25,30), +(1,4,26,43,63,41,25,31), +(1,4,27,44,65,42,25,31), +(1,4,28,45,67,43,25,32), +(1,4,29,46,69,43,25,32), +(1,4,30,47,71,44,26,33), +(1,4,31,48,72,45,26,33), +(1,4,32,49,74,46,26,34), +(1,4,33,50,76,47,27,34), +(1,4,34,51,78,48,27,35), +(1,4,35,52,80,49,27,35), +(1,4,36,53,82,50,27,36), +(1,4,37,54,84,51,28,36), +(1,4,38,55,86,52,28,37), +(1,4,39,56,88,53,28,38), +(1,4,40,57,90,54,28,38), +(1,4,41,58,92,55,29,39), +(1,4,42,60,94,56,29,39), +(1,4,43,61,96,57,29,40), +(1,4,44,62,98,58,30,40), +(1,4,45,63,100,59,30,41), +(1,4,46,64,103,61,30,42), +(1,4,47,65,105,62,31,42), +(1,4,48,66,107,63,31,43), +(1,4,49,68,109,64,31,44), +(1,4,50,69,111,65,32,44), +(1,4,51,70,113,66,32,45), +(1,4,52,71,116,67,32,45), +(1,4,53,73,118,68,33,46), +(1,4,54,74,120,69,33,47), +(1,4,55,75,122,71,33,47), +(1,4,56,76,125,72,34,48), +(1,4,57,78,127,73,34,49), +(1,4,58,79,129,74,34,49), +(1,4,59,80,131,75,35,50), +(1,4,60,81,134,77,35,51), +(1,4,61,83,136,78,35,51), +(1,4,62,84,138,79,36,52), +(1,4,63,85,141,80,36,53), +(1,4,64,87,143,81,37,54), +(1,4,65,88,146,83,37,54), +(1,4,66,89,148,84,37,55), +(1,4,67,91,151,85,38,56), +(1,4,68,92,153,86,38,57), +(1,4,69,94,156,88,39,57), +(1,4,70,95,158,89,39,58), +(1,4,71,97,161,90,39,60), +(1,4,72,99,164,92,40,60), +(1,4,73,100,167,94,40,61), +(1,4,74,102,170,95,41,62), +(1,4,75,104,173,97,41,63), +(1,4,76,105,176,98,41,64), +(1,4,77,107,179,100,42,65), +(1,4,78,109,183,106,42,66), +(1,4,79,111,186,107,43,67), +(1,4,80,113,189,109,43,69), + +(1,5,1,20,20,20,22,23), +(1,5,2,20,20,20,23,24), +(1,5,3,20,20,21,25,26), +(1,5,4,20,21,21,26,27), +(1,5,5,21,21,21,27,28), +(1,5,6,21,21,22,29,30), +(1,5,7,21,21,22,30,31), +(1,5,8,21,22,23,31,33), +(1,5,9,21,22,23,33,34), +(1,5,10,21,22,23,34,36), +(1,5,11,22,22,24,36,37), +(1,5,12,22,23,24,37,39), +(1,5,13,22,23,25,38,40), +(1,5,14,22,23,25,40,42), +(1,5,15,22,23,25,41,43), +(1,5,16,23,24,26,43,45), +(1,5,17,23,24,26,44,46), +(1,5,18,23,24,27,46,48), +(1,5,19,23,24,27,47,49), +(1,5,20,23,25,28,49,51), +(1,5,21,24,25,28,51,53), +(1,5,22,24,25,29,52,54), +(1,5,23,24,26,29,54,56), +(1,5,24,24,26,30,55,58), +(1,5,25,25,26,30,57,59), +(1,5,26,25,27,31,59,61), +(1,5,27,25,27,31,60,63), +(1,5,28,25,27,32,62,65), +(1,5,29,25,28,32,64,66), +(1,5,30,26,28,33,65,68), +(1,5,31,26,28,33,67,70), +(1,5,32,26,29,34,69,72), +(1,5,33,27,29,34,70,73), +(1,5,34,27,29,35,72,75), +(1,5,35,27,30,35,74,77), +(1,5,36,27,30,36,76,79), +(1,5,37,28,30,36,78,81), +(1,5,38,28,31,37,79,83), +(1,5,39,28,31,38,81,85), +(1,5,40,28,31,38,83,87), +(1,5,41,29,32,39,85,88), +(1,5,42,29,32,39,87,90), +(1,5,43,29,33,40,89,92), +(1,5,44,30,33,40,91,94), +(1,5,45,30,33,41,92,96), +(1,5,46,30,34,42,94,98), +(1,5,47,31,34,42,96,100), +(1,5,48,31,35,43,98,102), +(1,5,49,31,35,44,100,104), +(1,5,50,32,36,44,102,106), +(1,5,51,32,36,45,104,109), +(1,5,52,32,36,45,106,111), +(1,5,53,33,37,46,108,113), +(1,5,54,33,37,47,110,115), +(1,5,55,33,38,47,112,117), +(1,5,56,34,38,48,114,119), +(1,5,57,34,39,49,117,121), +(1,5,58,34,39,49,119,124), +(1,5,59,35,40,50,121,126), +(1,5,60,35,40,51,123,128), +(1,5,61,35,41,51,125,130), +(1,5,62,36,41,52,127,132), +(1,5,63,36,41,53,129,135), +(1,5,64,37,42,54,132,137), +(1,5,65,37,42,54,134,139), +(1,5,66,37,43,55,136,142), +(1,5,67,38,43,56,138,144), +(1,5,68,38,44,57,140,146), +(1,5,69,39,44,57,143,149), +(1,5,70,39,45,58,145,151), +(1,5,71,39,46,59,148,158), +(1,5,72,40,46,59,151,161), +(1,5,73,40,47,60,154,164), +(1,5,74,41,47,61,156,167), +(1,5,75,41,48,62,159,170), +(1,5,76,41,49,63,162,174), +(1,5,77,42,49,64,165,177), +(1,5,78,42,50,65,168,180), +(1,5,79,43,50,66,171,183), +(1,5,80,43,51,67,174,186), + +(1,6,1,23,20,22,20,20), +(1,6,2,24,21,23,20,20), +(1,6,3,26,22,24,20,21), +(1,6,4,27,22,26,20,21), +(1,6,5,28,23,27,20,21), +(1,6,6,30,24,28,20,21), +(1,6,7,31,25,29,21,22), +(1,6,8,32,26,30,21,22), +(1,6,9,34,26,32,21,22), +(1,6,10,35,27,33,21,23), +(1,6,11,36,28,34,21,23), +(1,6,12,38,29,35,21,23), +(1,6,13,39,30,37,21,24), +(1,6,14,41,31,38,21,24), +(1,6,15,42,32,39,21,24), +(1,6,16,44,33,41,21,25), +(1,6,17,45,34,42,22,25), +(1,6,18,47,34,43,22,25), +(1,6,19,48,35,45,22,26), +(1,6,20,50,36,46,22,26), +(1,6,21,51,37,48,22,26), +(1,6,22,53,38,49,22,27), +(1,6,23,54,39,51,22,27), +(1,6,24,56,40,52,23,28), +(1,6,25,58,41,53,23,28), +(1,6,26,59,42,55,23,28), +(1,6,27,61,43,56,23,29), +(1,6,28,63,44,58,23,29), +(1,6,29,64,45,59,23,30), +(1,6,30,66,46,61,24,30), +(1,6,31,68,47,62,24,30), +(1,6,32,69,48,64,24,31), +(1,6,33,71,50,66,24,31), +(1,6,34,73,51,67,24,32), +(1,6,35,74,52,69,24,32), +(1,6,36,76,53,70,25,33), +(1,6,37,78,54,72,25,33), +(1,6,38,80,55,74,25,34), +(1,6,39,82,56,75,25,34), +(1,6,40,83,57,77,25,35), +(1,6,41,85,58,79,26,35), +(1,6,42,87,60,80,26,35), +(1,6,43,89,61,82,26,36), +(1,6,44,91,62,84,26,36), +(1,6,45,93,63,85,26,37), +(1,6,46,95,64,87,27,37), +(1,6,47,97,66,89,27,38), +(1,6,48,99,67,91,27,38), +(1,6,49,101,68,93,27,39), +(1,6,50,103,69,94,28,40), +(1,6,51,105,71,96,28,40), +(1,6,52,106,72,97,28,41), +(1,6,53,107,72,98,28,41), +(1,6,54,107,73,98,29,42), +(1,6,55,108,73,99,29,43), +(1,6,56,111,75,102,29,44), +(1,6,57,113,76,104,29,44), +(1,6,58,118,77,106,30,45), +(1,6,59,118,79,108,30,45), +(1,6,60,123,80,110,30,46), +(1,6,61,125,81,112,30,47), +(1,6,62,128,83,114,30,47), +(1,6,63,130,84,117,31,48), +(1,6,64,130,86,119,31,48), +(1,6,65,140,87,128,31,49), +(1,6,66,143,89,131,31,50), +(1,6,67,146,90,133,32,50), +(1,6,68,148,92,135,32,51), +(1,6,69,151,93,138,32,52), +(1,6,70,154,95,140,32,52), +(1,6,71,162,97,144,33,53), +(1,6,72,164,98,146,33,54), +(1,6,73,165,100,148,33,55), +(1,6,74,166,102,151,33,55), +(1,6,75,169,103,154,34,56), +(1,6,76,172,105,157,34,57), +(1,6,77,175,107,157,34,58), +(1,6,78,176,108,157,34,58), +(1,6,79,177,110,157,35,59), +(1,6,80,180,112,160,35,60), + +(1,8,1,20,20,20,23,22), +(1,8,2,20,20,20,24,23), +(1,8,3,20,20,21,26,25), +(1,8,4,20,20,21,27,26), +(1,8,5,20,21,21,28,27), +(1,8,6,20,21,21,30,29), +(1,8,7,21,21,22,31,30), +(1,8,8,21,21,22,33,31), +(1,8,9,21,21,22,34,33), +(1,8,10,21,21,23,36,34), +(1,8,11,21,22,23,37,36), +(1,8,12,21,22,23,39,37), +(1,8,13,21,22,24,40,38), +(1,8,14,21,22,24,42,40), +(1,8,15,21,22,24,43,41), +(1,8,16,21,23,25,45,43), +(1,8,17,22,23,25,46,44), +(1,8,18,22,23,25,48,46), +(1,8,19,22,23,26,49,47), +(1,8,20,22,23,26,51,49), +(1,8,21,22,24,26,53,51), +(1,8,22,22,24,27,54,52), +(1,8,23,22,24,27,56,54), +(1,8,24,23,24,28,58,55), +(1,8,25,23,25,28,59,57), +(1,8,26,23,25,28,61,59), +(1,8,27,23,25,29,63,60), +(1,8,28,23,25,29,65,62), +(1,8,29,23,25,30,66,64), +(1,8,30,24,26,30,68,65), +(1,8,31,24,26,30,70,67), +(1,8,32,24,26,31,72,69), +(1,8,33,24,27,31,73,70), +(1,8,34,24,27,32,75,72), +(1,8,35,24,27,32,77,74), +(1,8,36,25,27,33,79,76), +(1,8,37,25,28,33,81,78), +(1,8,38,25,28,34,83,79), +(1,8,39,25,28,34,85,81), +(1,8,40,25,28,35,87,83), +(1,8,41,26,29,35,88,85), +(1,8,42,26,29,35,90,87), +(1,8,43,26,29,36,92,89), +(1,8,44,26,30,36,94,91), +(1,8,45,26,30,37,96,92), +(1,8,46,27,30,37,98,94), +(1,8,47,27,31,38,100,96), +(1,8,48,27,31,38,102,98), +(1,8,49,27,31,39,104,100), +(1,8,50,28,32,40,106,102), +(1,8,51,28,32,40,109,104), +(1,8,52,28,32,41,111,106), +(1,8,53,28,33,41,113,108), +(1,8,54,29,33,42,115,110), +(1,8,55,29,33,42,117,112), +(1,8,56,29,34,43,119,114), +(1,8,57,29,34,43,121,117), +(1,8,58,30,34,44,124,119), +(1,8,59,30,35,44,126,121), +(1,8,60,30,35,45,128,123), +(1,8,61,30,35,46,130,125), +(1,8,62,31,36,46,132,127), +(1,8,63,31,36,47,135,129), +(1,8,64,31,37,47,137,132), +(1,8,65,32,37,48,139,134), +(1,8,66,32,37,49,142,136), +(1,8,67,32,38,49,144,138), +(1,8,68,32,38,50,146,140), +(1,8,69,33,39,50,149,143), +(1,8,70,33,39,51,151,145), +(1,8,71,33,39,52,154,152), +(1,8,72,33,40,53,160,155), +(1,8,73,33,40,54,160,158), +(1,8,74,34,41,54,163,160), +(1,8,75,34,41,55,166,163), +(1,8,76,34,41,56,169,166), +(1,8,77,35,42,57,172,169), +(1,8,78,35,42,57,175,173), +(1,8,79,35,43,58,178,176), +(1,8,80,36,43,59,181,179), + +(1,9,1,20,20,21,22,22), +(1,9,2,20,20,22,23,23), +(1,9,3,21,21,22,24,24), +(1,9,4,21,21,23,26,25), +(1,9,5,21,21,23,27,27), +(1,9,6,21,22,24,28,28), +(1,9,7,22,22,24,29,29), +(1,9,8,22,23,25,30,30), +(1,9,9,22,23,26,32,31), +(1,9,10,23,23,26,33,33), +(1,9,11,23,24,27,34,34), +(1,9,12,23,24,27,35,35), +(1,9,13,24,25,28,37,36), +(1,9,14,24,25,29,38,38), +(1,9,15,24,25,29,39,39), +(1,9,16,25,26,30,41,40), +(1,9,17,25,26,31,42,42), +(1,9,18,25,27,31,43,43), +(1,9,19,26,27,32,45,44), +(1,9,20,26,28,33,46,46), +(1,9,21,26,28,33,48,47), +(1,9,22,27,29,34,49,49), +(1,9,23,27,29,35,51,50), +(1,9,24,28,30,35,52,51), +(1,9,25,28,30,36,53,53), +(1,9,26,28,31,37,55,54), +(1,9,27,29,31,37,56,56), +(1,9,28,29,32,38,58,57), +(1,9,29,30,32,39,59,59), +(1,9,30,30,33,40,61,60), +(1,9,31,30,33,40,62,62), +(1,9,32,31,34,41,64,63), +(1,9,33,31,34,42,66,65), +(1,9,34,32,35,43,67,66), +(1,9,35,32,35,44,69,68), +(1,9,36,33,36,44,70,69), +(1,9,37,33,36,45,72,71), +(1,9,38,34,37,46,74,73), +(1,9,39,34,38,47,75,74), +(1,9,40,35,38,48,77,76), +(1,9,41,35,39,48,79,78), +(1,9,42,35,39,49,80,79), +(1,9,43,36,40,50,82,81), +(1,9,44,36,40,51,84,83), +(1,9,45,37,41,52,85,84), +(1,9,46,37,42,53,87,86), +(1,9,47,38,42,54,89,88), +(1,9,48,38,43,55,91,89), +(1,9,49,39,44,55,93,91), +(1,9,50,40,44,56,94,93), +(1,9,51,40,45,57,96,95), +(1,9,52,41,45,58,98,97), +(1,9,53,41,46,59,100,98), +(1,9,54,42,47,60,102,100), +(1,9,55,42,47,61,103,102), +(1,9,56,43,48,62,105,104), +(1,9,57,43,49,63,107,106), +(1,9,58,44,49,64,109,108), +(1,9,59,44,50,65,111,109), +(1,9,60,45,51,66,113,111), +(1,9,61,46,51,67,115,113), +(1,9,62,46,52,68,117,115), +(1,9,63,47,53,69,119,117), +(1,9,64,47,54,70,121,119), +(1,9,65,48,54,71,123,121), +(1,9,66,49,55,72,125,123), +(1,9,67,49,56,73,127,125), +(1,9,68,50,57,74,129,127), +(1,9,69,50,57,75,131,129), +(1,9,70,51,58,76,133,131), +(1,9,71,52,59,78,135,146), +(1,9,72,53,59,79,138,148), +(1,9,73,54,60,80,140,151), +(1,9,74,54,61,89,143,154), +(1,9,75,55,62,91,145,156), +(1,9,76,56,63,92,148,159), +(1,9,77,57,64,93,151,162), +(1,9,78,57,65,95,153,165), +(1,9,79,58,66,96,156,168), +(1,9,80,59,67,97,159,170), + +(2,1,1,26,17,24,17,23), +(2,1,2,27,18,25,17,23), +(2,1,3,29,19,26,17,24), +(2,1,4,30,19,27,17,24), +(2,1,5,31,20,29,17,24), +(2,1,6,32,21,30,17,24), +(2,1,7,34,22,31,18,25), +(2,1,8,35,23,32,18,25), +(2,1,9,37,24,34,18,25), +(2,1,10,38,24,35,18,26), +(2,1,11,39,25,36,18,26), +(2,1,12,41,26,37,18,26), +(2,1,13,42,27,39,18,27), +(2,1,14,44,28,40,18,27), +(2,1,15,45,29,41,18,27), +(2,1,16,47,30,43,19,28), +(2,1,17,48,31,44,19,28), +(2,1,18,50,32,45,19,28), +(2,1,19,51,33,47,19,29), +(2,1,20,53,34,48,19,29), +(2,1,21,54,34,50,19,29), +(2,1,22,56,35,51,19,30), +(2,1,23,57,36,52,20,30), +(2,1,24,59,37,54,20,30), +(2,1,25,60,38,55,20,31), +(2,1,26,62,39,57,20,31), +(2,1,27,64,40,58,20,32), +(2,1,28,65,41,60,20,32), +(2,1,29,67,43,61,21,32), +(2,1,30,69,44,63,21,33), +(2,1,31,70,45,64,21,33), +(2,1,32,72,46,66,21,34), +(2,1,33,74,47,67,21,34), +(2,1,34,76,48,69,21,35), +(2,1,35,77,49,71,22,35), +(2,1,36,79,50,72,22,36), +(2,1,37,81,51,74,22,36), +(2,1,38,83,52,76,22,36), +(2,1,39,84,53,77,22,37), +(2,1,40,86,55,79,23,37), +(2,1,41,88,56,81,23,38), +(2,1,42,90,57,82,23,38), +(2,1,43,92,58,84,23,39), +(2,1,44,94,59,86,23,39), +(2,1,45,96,60,87,24,40), +(2,1,46,98,62,89,24,40), +(2,1,47,100,63,91,24,41), +(2,1,48,101,64,93,24,41), +(2,1,49,103,65,94,25,42), +(2,1,50,105,66,96,25,42), +(2,1,51,107,68,98,25,43), +(2,1,52,109,69,100,25,43), +(2,1,53,111,70,102,25,44), +(2,1,54,113,71,104,26,45), +(2,1,55,115,73,105,26,45), +(2,1,56,118,74,107,26,46), +(2,1,57,120,75,109,26,46), +(2,1,58,122,77,111,27,47), +(2,1,59,124,78,113,27,47), +(2,1,60,126,79,115,27,48), +(2,1,61,128,81,117,27,48), +(2,1,62,130,82,119,28,49), +(2,1,63,132,83,121,28,50), +(2,1,64,135,85,123,28,50), +(2,1,65,137,86,125,29,51), +(2,1,66,139,87,127,29,52), +(2,1,67,141,89,129,29,52), +(2,1,68,143,90,131,29,53), +(2,1,69,146,92,133,30,53), +(2,1,70,148,93,135,30,54), +(2,1,71,157,94,142,30,55), +(2,1,72,162,96,148,30,56), +(2,1,73,165,98,150,30,57), +(2,1,74,168,99,153,31,57), +(2,1,75,170,101,154,31,58), +(2,1,76,172,103,156,31,59), +(2,1,77,174,105,159,32,60), +(2,1,78,179,106,162,32,60), +(2,1,79,184,108,167,32,61), +(2,1,80,187,110,170,33,62), + +(2,3,1,23,20,23,17,24), +(2,3,2,23,21,24,18,25), +(2,3,3,24,23,25,18,25), +(2,3,4,24,24,26,19,26), +(2,3,5,25,25,27,19,26), +(2,3,6,25,27,28,20,27), +(2,3,7,26,28,28,21,28), +(2,3,8,26,30,29,21,28), +(2,3,9,26,31,30,22,29), +(2,3,10,27,33,31,22,30), +(2,3,11,27,34,32,23,30), +(2,3,12,28,36,33,24,31), +(2,3,13,28,37,34,24,32), +(2,3,14,29,39,35,25,33), +(2,3,15,29,40,36,26,33), +(2,3,16,30,42,37,26,34), +(2,3,17,30,43,39,27,35), +(2,3,18,31,45,40,28,35), +(2,3,19,31,47,41,28,36), +(2,3,20,32,48,42,29,37), +(2,3,21,32,50,43,30,38), +(2,3,22,33,51,44,31,39), +(2,3,23,34,53,45,31,39), +(2,3,24,34,55,46,32,40), +(2,3,25,35,57,47,33,41), +(2,3,26,35,58,48,34,42), +(2,3,27,36,60,50,34,43), +(2,3,28,36,62,51,35,43), +(2,3,29,37,63,52,36,44), +(2,3,30,38,65,53,37,45), +(2,3,31,38,67,54,37,46), +(2,3,32,39,69,56,38,47), +(2,3,33,39,71,57,39,48), +(2,3,34,40,72,58,40,49), +(2,3,35,41,74,59,41,49), +(2,3,36,41,76,61,42,50), +(2,3,37,42,78,62,42,51), +(2,3,38,43,80,63,43,52), +(2,3,39,43,82,64,44,53), +(2,3,40,44,84,66,45,54), +(2,3,41,45,86,67,46,55), +(2,3,42,45,88,68,47,56), +(2,3,43,46,90,70,47,57), +(2,3,44,47,91,71,48,58), +(2,3,45,47,93,72,49,59), +(2,3,46,48,95,74,50,60), +(2,3,47,49,98,75,51,61), +(2,3,48,50,100,77,52,62), +(2,3,49,50,102,78,53,63), +(2,3,50,51,104,79,54,64), +(2,3,51,52,106,81,55,65), +(2,3,52,52,108,82,56,66), +(2,3,53,53,110,84,57,67), +(2,3,54,54,112,85,58,68), +(2,3,55,55,114,87,59,69), +(2,3,56,55,116,88,60,70), +(2,3,57,56,118,90,61,71), +(2,3,58,57,121,91,62,72), +(2,3,59,58,123,93,63,73), +(2,3,60,59,125,94,64,74), +(2,3,61,59,127,96,65,76), +(2,3,62,60,130,97,66,77), +(2,3,63,61,132,99,67,78), +(2,3,64,62,134,100,68,79), +(2,3,65,63,136,102,69,80), +(2,3,66,64,139,104,70,81), +(2,3,67,64,141,105,71,82), +(2,3,68,65,143,107,72,84), +(2,3,69,66,146,108,73,85), +(2,3,70,67,148,110,74,86), +(2,3,71,68,151,112,75,87), +(2,3,72,69,154,114,76,88), +(2,3,73,70,157,116,77,90), +(2,3,74,71,160,118,79,91), +(2,3,75,72,163,120,80,93), +(2,3,76,73,166,122,81,94), +(2,3,77,74,169,124,83,96), +(2,3,78,75,172,126,84,97), +(2,3,79,76,175,128,85,99), +(2,3,80,77,178,130,87,100), + +(2,4,1,24,20,23,17,23), +(2,4,2,25,21,24,17,23), +(2,4,3,25,23,24,17,24), +(2,4,4,26,24,25,17,24), +(2,4,5,27,26,26,18,24), +(2,4,6,28,27,26,18,25), +(2,4,7,29,29,27,18,25), +(2,4,8,29,30,28,18,26), +(2,4,9,30,32,29,18,26), +(2,4,10,31,33,29,19,26), +(2,4,11,32,35,30,19,27), +(2,4,12,33,37,31,19,27), +(2,4,13,34,38,32,19,28), +(2,4,14,34,40,32,19,28), +(2,4,15,35,41,33,19,28), +(2,4,16,36,43,34,20,29), +(2,4,17,37,45,35,20,29), +(2,4,18,38,46,36,20,30), +(2,4,19,39,48,37,20,30), +(2,4,20,40,50,37,21,31), +(2,4,21,41,52,38,21,31), +(2,4,22,42,53,39,21,31), +(2,4,23,43,55,40,21,32), +(2,4,24,43,57,41,21,32), +(2,4,25,44,59,42,22,33), +(2,4,26,45,60,43,22,33), +(2,4,27,46,62,44,22,34), +(2,4,28,47,64,44,22,34), +(2,4,29,48,66,45,23,35), +(2,4,30,49,68,46,23,35), +(2,4,31,50,70,47,23,36), +(2,4,32,51,72,48,23,36), +(2,4,33,53,73,49,24,37), +(2,4,34,54,75,50,24,38), +(2,4,35,55,77,51,24,38), +(2,4,36,56,79,52,24,39), +(2,4,37,57,81,53,25,39), +(2,4,38,58,83,54,25,40), +(2,4,39,59,85,55,25,40), +(2,4,40,60,87,56,26,41), +(2,4,41,61,89,57,26,41), +(2,4,42,62,91,58,26,42), +(2,4,43,63,93,59,27,43), +(2,4,44,65,95,60,27,43), +(2,4,45,66,98,61,27,44), +(2,4,46,67,100,62,27,44), +(2,4,47,68,102,64,28,45), +(2,4,48,69,104,65,28,46), +(2,4,49,71,106,66,28,46), +(2,4,50,72,108,67,29,47), +(2,4,51,73,110,68,29,48), +(2,4,52,74,113,69,29,48), +(2,4,53,75,115,70,30,49), +(2,4,54,77,117,71,30,50), +(2,4,55,78,119,73,30,50), +(2,4,56,79,122,74,31,51), +(2,4,57,80,124,75,31,52), +(2,4,58,82,126,76,31,52), +(2,4,59,83,129,77,32,53), +(2,4,60,84,131,78,32,54), +(2,4,61,86,133,80,33,54), +(2,4,62,87,136,81,33,55), +(2,4,63,88,138,82,33,56), +(2,4,64,90,140,83,34,57), +(2,4,65,91,143,85,34,57), +(2,4,66,92,145,86,34,58), +(2,4,67,94,148,87,35,59), +(2,4,68,95,150,88,35,59), +(2,4,69,97,153,90,36,60), +(2,4,70,98,155,91,36,61), +(2,4,71,100,158,92,36,62), +(2,4,72,102,161,94,37,62), +(2,4,73,103,164,99,37,63), +(2,4,74,105,167,100,38,64), +(2,4,75,107,170,102,38,65), +(2,4,76,108,173,102,38,66), +(2,4,77,110,176,102,39,67), +(2,4,78,112,180,103,39,68), +(2,4,79,114,183,105,40,69), +(2,4,80,116,186,107,40,70), + +(2,6,1,26,17,24,17,23), +(2,6,2,27,18,25,17,23), +(2,6,3,29,19,26,17,24), +(2,6,4,30,19,27,17,24), +(2,6,5,31,20,29,17,24), +(2,6,6,32,21,30,17,24), +(2,6,7,34,22,31,18,25), +(2,6,8,35,23,32,18,25), +(2,6,9,37,24,34,18,25), +(2,6,10,38,24,35,18,26), +(2,6,11,39,25,36,18,26), +(2,6,12,41,26,37,18,26), +(2,6,13,42,27,39,18,27), +(2,6,14,44,28,40,18,27), +(2,6,15,45,29,41,18,27), +(2,6,16,47,30,43,19,28), +(2,6,17,48,31,44,19,28), +(2,6,18,50,32,45,19,28), +(2,6,19,51,33,47,19,29), +(2,6,20,53,34,48,19,29), +(2,6,21,54,34,50,19,29), +(2,6,22,56,35,51,19,30), +(2,6,23,57,36,52,20,30), +(2,6,24,59,37,54,20,30), +(2,6,25,60,38,55,20,31), +(2,6,26,62,39,57,20,31), +(2,6,27,64,40,58,20,32), +(2,6,28,65,41,60,20,32), +(2,6,29,67,43,61,21,32), +(2,6,30,69,44,63,21,33), +(2,6,31,70,45,64,21,33), +(2,6,32,72,46,66,21,34), +(2,6,33,74,47,67,21,34), +(2,6,34,76,48,69,21,35), +(2,6,35,77,49,71,22,35), +(2,6,36,79,50,72,22,36), +(2,6,37,81,51,74,22,36), +(2,6,38,83,52,76,22,36), +(2,6,39,84,53,77,22,37), +(2,6,40,86,55,79,23,37), +(2,6,41,88,56,81,23,38), +(2,6,42,90,57,82,23,38), +(2,6,43,92,58,84,23,39), +(2,6,44,94,59,86,23,39), +(2,6,45,96,60,87,24,40), +(2,6,46,98,62,89,24,40), +(2,6,47,100,63,91,24,41), +(2,6,48,101,64,93,24,41), +(2,6,49,103,65,94,25,42), +(2,6,50,105,66,96,25,42), +(2,6,51,107,68,98,25,43), +(2,6,52,109,69,100,25,43), +(2,6,53,110,69,100,25,44), +(2,6,54,111,70,101,26,45), +(2,6,55,111,70,101,26,45), +(2,6,56,114,72,104,26,46), +(2,6,57,116,73,106,26,46), +(2,6,58,118,74,108,27,47), +(2,6,59,124,76,110,27,47), +(2,6,60,126,77,112,27,48), +(2,6,61,128,78,114,27,49), +(2,6,62,131,80,116,27,49), +(2,6,63,133,81,119,28,50), +(2,6,64,136,83,121,28,50), +(2,6,65,136,84,123,28,51), +(2,6,66,142,86,126,28,52), +(2,6,67,145,87,128,29,52), +(2,6,68,147,89,130,29,53), +(2,6,69,150,90,133,29,54), +(2,6,70,157,92,135,29,54), +(2,6,71,160,94,138,30,55), +(2,6,72,163,95,140,30,56), +(2,6,73,166,97,151,30,57), +(2,6,74,169,99,154,30,57), +(2,6,75,172,100,156,31,58), +(2,6,76,175,102,160,31,59), +(2,6,77,179,104,162,31,60), +(2,6,78,182,105,165,31,60), +(2,6,79,191,107,168,32,61), +(2,6,80,194,109,171,32,62), + +(2,7,1,24,17,23,18,25), +(2,7,2,25,17,24,19,26), +(2,7,3,26,18,25,20,27), +(2,7,4,26,18,26,21,28), +(2,7,5,27,19,27,22,29), +(2,7,6,28,19,28,23,30), +(2,7,7,29,20,29,24,31), +(2,7,8,30,20,30,25,32), +(2,7,9,31,21,31,26,33), +(2,7,10,32,21,32,27,34), +(2,7,11,33,22,33,28,36), +(2,7,12,34,22,34,29,37), +(2,7,13,34,23,35,30,38), +(2,7,14,35,23,36,31,39), +(2,7,15,36,24,37,32,40), +(2,7,16,37,24,39,33,41), +(2,7,17,38,25,40,34,43), +(2,7,18,39,25,41,35,44), +(2,7,19,40,26,42,36,45), +(2,7,20,41,26,43,37,46), +(2,7,21,42,27,44,38,47), +(2,7,22,43,27,45,39,49), +(2,7,23,44,28,47,40,50), +(2,7,24,45,28,48,41,51), +(2,7,25,47,29,49,43,52), +(2,7,26,48,30,50,44,54), +(2,7,27,49,30,52,45,55), +(2,7,28,50,31,53,46,56), +(2,7,29,51,31,54,47,58), +(2,7,30,52,32,55,48,59), +(2,7,31,53,33,57,50,60), +(2,7,32,54,33,58,51,62), +(2,7,33,55,34,59,52,63), +(2,7,34,57,34,61,53,65), +(2,7,35,58,35,62,55,66), +(2,7,36,59,36,63,56,67), +(2,7,37,60,36,65,57,69), +(2,7,38,61,37,66,58,70), +(2,7,39,62,38,67,60,72), +(2,7,40,64,38,69,61,73), +(2,7,41,65,39,70,62,75), +(2,7,42,66,40,72,64,76), +(2,7,43,67,40,73,65,78), +(2,7,44,69,41,74,66,79), +(2,7,45,70,42,76,68,81), +(2,7,46,71,42,77,69,82), +(2,7,47,72,43,79,70,84), +(2,7,48,74,44,80,72,85), +(2,7,49,75,45,82,73,87), +(2,7,50,76,45,83,75,89), +(2,7,51,78,46,85,76,90), +(2,7,52,79,47,86,77,92), +(2,7,53,80,47,88,79,93), +(2,7,54,82,48,90,80,95), +(2,7,55,83,49,91,82,97), +(2,7,56,85,50,93,83,98), +(2,7,57,86,50,94,85,100), +(2,7,58,87,51,96,86,102), +(2,7,59,89,52,97,88,103), +(2,7,60,90,53,99,89,105), +(2,7,61,92,54,101,91,107), +(2,7,62,93,54,102,92,109), +(2,7,63,95,55,104,94,110), +(2,7,64,96,56,106,95,112), +(2,7,65,97,57,107,97,114), +(2,7,66,99,58,109,99,116), +(2,7,67,100,58,111,100,118), +(2,7,68,102,59,113,102,119), +(2,7,69,103,60,114,103,121), +(2,7,70,105,61,116,105,123), +(2,7,71,106,62,118,117,125), +(2,7,72,108,63,120,119,128), +(2,7,73,110,64,122,122,130), +(2,7,74,112,65,125,124,132), +(2,7,75,114,66,127,126,134), +(2,7,76,116,67,129,128,137), +(2,7,77,117,68,131,128,139), +(2,7,78,119,69,133,133,141), +(2,7,79,121,70,136,135,144), +(2,7,80,123,71,138,137,146), + +(2,9,1,23,17,23,19,25), +(2,9,2,23,17,24,20,26), +(2,9,3,24,18,24,21,27), +(2,9,4,24,18,25,23,28), +(2,9,5,24,18,25,24,30), +(2,9,6,24,19,26,25,31), +(2,9,7,25,19,26,26,32), +(2,9,8,25,20,27,27,33), +(2,9,9,25,20,27,29,34), +(2,9,10,26,20,28,30,36), +(2,9,11,26,21,29,31,37), +(2,9,12,26,21,29,33,38), +(2,9,13,27,22,30,34,39), +(2,9,14,27,22,31,35,41), +(2,9,15,27,23,31,37,42), +(2,9,16,28,23,32,38,43), +(2,9,17,28,23,32,39,45), +(2,9,18,28,24,33,41,46), +(2,9,19,29,24,34,42,47), +(2,9,20,29,25,34,43,49), +(2,9,21,29,25,35,45,50), +(2,9,22,30,26,36,46,51), +(2,9,23,30,26,37,48,53), +(2,9,24,30,27,37,49,54), +(2,9,25,31,27,38,51,56), +(2,9,26,31,28,39,52,57), +(2,9,27,32,28,39,54,59), +(2,9,28,32,29,40,55,60), +(2,9,29,32,29,41,57,62), +(2,9,30,33,30,42,58,63), +(2,9,31,33,30,42,60,65), +(2,9,32,34,31,43,61,66), +(2,9,33,34,31,44,63,68), +(2,9,34,35,32,45,64,69), +(2,9,35,35,32,45,66,71), +(2,9,36,36,33,46,68,72), +(2,9,37,36,34,47,69,74), +(2,9,38,36,34,48,71,76), +(2,9,39,37,35,49,72,77), +(2,9,40,37,35,50,74,79), +(2,9,41,38,36,50,76,80), +(2,9,42,38,36,51,77,82), +(2,9,43,39,37,52,79,84), +(2,9,44,39,38,53,81,85), +(2,9,45,40,38,54,83,87), +(2,9,46,40,39,55,84,89), +(2,9,47,41,39,56,86,91), +(2,9,48,41,40,56,88,92), +(2,9,49,42,41,57,90,94), +(2,9,50,42,41,58,91,96), +(2,9,51,43,42,59,93,98), +(2,9,52,43,43,60,95,99), +(2,9,53,44,43,61,97,101), +(2,9,54,45,44,62,99,103), +(2,9,55,45,45,63,101,105), +(2,9,56,46,45,64,102,107), +(2,9,57,46,46,65,104,109), +(2,9,58,47,47,66,106,110), +(2,9,59,47,47,67,108,112), +(2,9,60,48,48,68,110,114), +(2,9,61,48,49,69,112,116), +(2,9,62,49,49,70,114,118), +(2,9,63,50,50,71,116,120), +(2,9,64,50,51,72,118,122), +(2,9,65,51,51,73,120,124), +(2,9,66,52,52,74,122,126), +(2,9,67,52,53,75,124,128), +(2,9,68,53,54,76,126,130), +(2,9,69,53,54,77,128,132), +(2,9,70,54,55,78,130,134), +(2,9,71,55,56,88,134,145), +(2,9,72,56,56,89,135,147), +(2,9,73,57,57,90,137,150), +(2,9,74,57,58,91,142,153), +(2,9,75,58,59,93,142,155), +(2,9,76,59,60,94,145,158), +(2,9,77,60,61,95,148,161), +(2,9,78,60,62,97,150,164), +(2,9,79,61,63,98,153,167), +(2,9,80,62,64,99,156,169), + +(3,1,1,25,16,25,19,19), +(3,1,2,26,17,26,19,19), +(3,1,3,28,18,27,19,20), +(3,1,4,29,18,28,19,20), +(3,1,5,30,19,30,19,20), +(3,1,6,31,20,31,19,20), +(3,1,7,33,21,32,20,21), +(3,1,8,34,22,33,20,21), +(3,1,9,36,23,35,20,21), +(3,1,10,37,23,36,20,22), +(3,1,11,38,24,37,20,22), +(3,1,12,40,25,38,20,22), +(3,1,13,41,26,40,20,23), +(3,1,14,43,27,41,20,23), +(3,1,15,44,28,42,20,23), +(3,1,16,46,29,44,21,24), +(3,1,17,47,30,45,21,24), +(3,1,18,49,31,46,21,24), +(3,1,19,50,32,48,21,25), +(3,1,20,52,33,49,21,25), +(3,1,21,53,34,51,21,26), +(3,1,22,55,34,52,21,26), +(3,1,23,56,35,53,21,26), +(3,1,24,58,36,55,22,27), +(3,1,25,59,37,56,22,27), +(3,1,26,61,38,58,22,27), +(3,1,27,63,39,59,22,28), +(3,1,28,64,41,61,22,28), +(3,1,29,66,42,62,22,29), +(3,1,30,68,43,64,23,29), +(3,1,31,69,44,65,23,30), +(3,1,32,71,45,67,23,30), +(3,1,33,73,46,68,23,30), +(3,1,34,75,47,70,23,31), +(3,1,35,76,48,72,24,31), +(3,1,36,78,49,73,24,32), +(3,1,37,80,50,75,24,32), +(3,1,38,82,51,76,24,33), +(3,1,39,84,52,78,24,33), +(3,1,40,85,54,80,24,34), +(3,1,41,87,55,81,25,34), +(3,1,42,89,56,83,25,35), +(3,1,43,91,57,85,25,35), +(3,1,44,93,58,87,25,36), +(3,1,45,95,59,88,26,36), +(3,1,46,97,61,90,26,37), +(3,1,47,99,62,92,26,37), +(3,1,48,101,63,94,26,38), +(3,1,49,102,64,95,26,38), +(3,1,50,104,65,97,27,39), +(3,1,51,106,67,99,27,39), +(3,1,52,108,68,101,27,40), +(3,1,53,110,69,103,27,40), +(3,1,54,112,70,104,28,41), +(3,1,55,115,72,106,28,41), +(3,1,56,117,73,108,28,42), +(3,1,57,119,74,110,28,42), +(3,1,58,121,76,112,29,43), +(3,1,59,123,77,114,29,43), +(3,1,60,125,78,116,29,44), +(3,1,61,127,80,118,29,45), +(3,1,62,129,81,120,30,45), +(3,1,63,131,82,122,30,46), +(3,1,64,134,84,124,30,46), +(3,1,65,136,85,126,31,47), +(3,1,66,138,86,128,31,48), +(3,1,67,140,88,130,31,48), +(3,1,68,142,89,132,31,49), +(3,1,69,145,91,134,32,49), +(3,1,70,147,92,136,32,50), +(3,1,71,150,93,138,32,51), +(3,1,72,152,95,141,32,52), +(3,1,73,164,97,151,32,53), +(3,1,74,164,98,151,33,53), +(3,1,75,170,100,156,33,54), +(3,1,76,173,102,160,33,55), +(3,1,77,173,104,160,34,56), +(3,1,78,176,105,162,34,56), +(3,1,79,183,107,168,34,57), +(3,1,80,186,109,171,35,58), + +(3,2,1,24,16,25,19,20), +(3,2,2,25,17,26,20,21), +(3,2,3,26,17,27,20,21), +(3,2,4,27,18,28,21,22), +(3,2,5,28,18,29,22,23), +(3,2,6,29,19,30,22,24), +(3,2,7,31,20,31,23,24), +(3,2,8,32,20,32,24,25), +(3,2,9,33,21,33,24,26), +(3,2,10,34,21,34,25,26), +(3,2,11,35,22,36,26,27), +(3,2,12,36,23,37,26,28), +(3,2,13,38,23,38,27,29), +(3,2,14,39,24,39,28,30), +(3,2,15,40,25,40,29,30), +(3,2,16,41,25,41,29,31), +(3,2,17,43,26,43,30,32), +(3,2,18,44,27,44,31,33), +(3,2,19,45,28,45,32,34), +(3,2,20,47,28,46,32,35), +(3,2,21,48,29,47,33,35), +(3,2,22,49,30,49,34,36), +(3,2,23,51,30,50,35,37), +(3,2,24,52,31,51,36,38), +(3,2,25,53,32,52,36,39), +(3,2,26,55,33,54,37,40), +(3,2,27,56,33,55,38,41), +(3,2,28,57,34,56,39,42), +(3,2,29,59,35,58,40,43), +(3,2,30,60,36,59,41,43), +(3,2,31,62,37,60,42,44), +(3,2,32,63,37,62,42,45), +(3,2,33,65,38,63,43,46), +(3,2,34,66,39,65,44,47), +(3,2,35,68,40,66,45,48), +(3,2,36,69,41,67,46,49), +(3,2,37,71,41,69,47,50), +(3,2,38,72,42,70,48,51), +(3,2,39,74,43,72,49,52), +(3,2,40,75,44,73,50,53), +(3,2,41,77,45,75,51,54), +(3,2,42,78,46,76,52,55), +(3,2,43,80,47,78,53,56), +(3,2,44,82,47,79,54,57), +(3,2,45,83,48,81,55,59), +(3,2,46,85,49,82,56,60), +(3,2,47,87,50,84,57,61), +(3,2,48,88,51,85,58,62), +(3,2,49,90,52,87,59,63), +(3,2,50,92,53,89,60,64), +(3,2,51,93,54,90,61,65), +(3,2,52,95,55,92,62,66), +(3,2,53,97,56,93,63,67), +(3,2,54,98,57,95,64,69), +(3,2,55,100,58,97,65,70), +(3,2,56,102,59,98,66,71), +(3,2,57,104,60,100,67,72), +(3,2,58,106,61,102,68,73), +(3,2,59,107,62,103,69,74), +(3,2,60,109,63,105,70,76), +(3,2,61,111,64,107,72,77), +(3,2,62,113,65,109,73,78), +(3,2,63,115,66,110,74,79), +(3,2,64,117,67,112,75,80), +(3,2,65,118,68,114,76,82), +(3,2,66,120,69,116,77,83), +(3,2,67,122,70,118,78,84), +(3,2,68,124,71,119,80,85), +(3,2,69,126,72,121,81,87), +(3,2,70,128,73,123,82,88), +(3,2,71,150,74,125,83,89), +(3,2,72,152,75,128,85,91), +(3,2,73,156,76,130,86,93), +(3,2,74,158,78,132,88,94), +(3,2,75,161,79,134,89,96), +(3,2,76,164,80,137,91,97), +(3,2,77,166,82,139,92,99), +(3,2,78,170,83,141,94,101), +(3,2,79,172,84,144,95,102), +(3,2,80,175,86,146,97,104), + +(3,3,1,22,19,24,19,20), +(3,3,2,22,20,25,20,21), +(3,3,3,23,22,26,20,21), +(3,3,4,23,23,27,21,22), +(3,3,5,24,25,28,21,23), +(3,3,6,24,26,29,22,23), +(3,3,7,25,27,29,23,24), +(3,3,8,25,29,30,23,25), +(3,3,9,25,30,31,24,25), +(3,3,10,26,32,32,24,26), +(3,3,11,26,33,33,25,27), +(3,3,12,27,35,34,26,27), +(3,3,13,27,36,35,26,28), +(3,3,14,28,38,36,27,29), +(3,3,15,28,39,37,28,29), +(3,3,16,29,41,38,28,30), +(3,3,17,29,42,39,29,31), +(3,3,18,30,44,41,30,32), +(3,3,19,30,46,42,30,32), +(3,3,20,31,47,43,31,33), +(3,3,21,32,49,44,32,34), +(3,3,22,32,51,45,33,35), +(3,3,23,33,52,46,33,36), +(3,3,24,33,54,47,34,36), +(3,3,25,34,56,48,35,37), +(3,3,26,34,57,49,35,38), +(3,3,27,35,59,51,36,39), +(3,3,28,35,61,52,37,40), +(3,3,29,36,63,53,38,40), +(3,3,30,37,64,54,39,41), +(3,3,31,37,66,55,39,42), +(3,3,32,38,68,57,40,43), +(3,3,33,38,70,58,41,44), +(3,3,34,39,71,59,42,45), +(3,3,35,40,73,60,43,46), +(3,3,36,40,75,62,43,47), +(3,3,37,41,77,63,44,47), +(3,3,38,42,79,64,45,48), +(3,3,39,42,81,65,46,49), +(3,3,40,43,83,67,47,50), +(3,3,41,44,85,68,48,51), +(3,3,42,44,87,69,49,52), +(3,3,43,45,89,71,49,53), +(3,3,44,46,91,72,50,54), +(3,3,45,46,93,73,51,55), +(3,3,46,47,95,75,52,56), +(3,3,47,48,97,76,53,57), +(3,3,48,49,99,78,54,58), +(3,3,49,49,101,79,55,59), +(3,3,50,50,103,80,56,60), +(3,3,51,51,105,82,57,61), +(3,3,52,51,107,83,58,62), +(3,3,53,52,109,85,59,63), +(3,3,54,53,111,86,60,64), +(3,3,55,54,113,88,61,65), +(3,3,56,55,115,89,62,66), +(3,3,57,55,118,91,62,67), +(3,3,58,56,120,92,63,68), +(3,3,59,57,122,94,64,70), +(3,3,60,58,124,95,65,71), +(3,3,61,58,126,97,67,72), +(3,3,62,59,129,98,68,73), +(3,3,63,60,131,100,69,74), +(3,3,64,61,133,101,70,75), +(3,3,65,62,135,103,71,76), +(3,3,66,63,138,105,72,77), +(3,3,67,63,140,106,73,78), +(3,3,68,64,142,108,74,80), +(3,3,69,65,145,109,75,81), +(3,3,70,66,147,111,76,82), +(3,3,71,67,150,113,77,83), +(3,3,72,68,153,115,78,84), +(3,3,73,69,156,117,79,86), +(3,3,74,70,159,119,81,87), +(3,3,75,71,162,121,82,89), +(3,3,76,72,165,123,83,90), +(3,3,77,73,168,125,85,92), +(3,3,78,74,171,127,86,93), +(3,3,79,75,174,129,87,95), +(3,3,80,76,177,131,89,96), + +(3,4,1,23,19,24,19,19), +(3,4,2,24,20,25,19,19), +(3,4,3,24,22,25,19,20), +(3,4,4,25,23,26,19,20), +(3,4,5,26,25,27,20,20), +(3,4,6,27,26,27,20,21), +(3,4,7,28,28,28,20,21), +(3,4,8,28,29,29,20,22), +(3,4,9,29,31,30,20,22), +(3,4,10,30,32,30,20,22), +(3,4,11,31,34,31,21,23), +(3,4,12,32,36,32,21,23), +(3,4,13,33,37,33,21,24), +(3,4,14,33,39,33,21,24), +(3,4,15,34,40,34,21,25), +(3,4,16,35,42,35,22,25), +(3,4,17,36,44,36,22,25), +(3,4,18,37,45,37,22,26), +(3,4,19,38,47,38,22,26), +(3,4,20,39,49,38,22,27), +(3,4,21,40,51,39,23,27), +(3,4,22,41,52,40,23,28), +(3,4,23,42,54,41,23,28), +(3,4,24,43,56,42,23,29), +(3,4,25,44,58,43,24,29), +(3,4,26,44,59,44,24,30), +(3,4,27,45,61,44,24,30), +(3,4,28,46,63,45,24,31), +(3,4,29,47,65,46,25,31), +(3,4,30,48,67,47,25,32), +(3,4,31,49,69,48,25,32), +(3,4,32,51,71,49,25,33), +(3,4,33,52,72,50,26,33), +(3,4,34,53,74,51,26,34), +(3,4,35,54,76,52,26,34), +(3,4,36,55,78,53,26,35), +(3,4,37,56,80,54,27,35), +(3,4,38,57,82,55,27,36), +(3,4,39,58,84,56,27,37), +(3,4,40,59,86,57,28,37), +(3,4,41,60,88,58,28,38), +(3,4,42,61,90,59,28,38), +(3,4,43,63,92,60,28,39), +(3,4,44,64,95,61,29,39), +(3,4,45,65,97,62,29,40), +(3,4,46,66,99,63,29,41), +(3,4,47,67,101,64,30,41), +(3,4,48,68,103,66,30,42), +(3,4,49,70,105,67,30,43), +(3,4,50,71,107,68,31,43), +(3,4,51,72,110,69,31,44), +(3,4,52,73,112,70,31,44), +(3,4,53,74,114,71,32,45), +(3,4,54,76,116,72,32,46), +(3,4,55,77,118,73,32,46), +(3,4,56,78,121,75,33,47), +(3,4,57,80,123,76,33,48), +(3,4,58,81,125,77,33,48), +(3,4,59,82,128,78,34,49), +(3,4,60,83,130,79,34,50), +(3,4,61,85,132,81,34,51), +(3,4,62,86,135,82,35,51), +(3,4,63,87,137,83,35,52), +(3,4,64,89,139,84,36,53), +(3,4,65,90,142,86,36,53), +(3,4,66,91,144,87,36,54), +(3,4,67,93,147,88,37,55), +(3,4,68,94,149,89,37,56), +(3,4,69,96,152,91,38,56), +(3,4,70,97,154,92,38,57), +(3,4,71,99,157,93,38,58), +(3,4,72,101,160,96,39,58), +(3,4,73,102,163,97,39,59), +(3,4,74,104,166,98,40,60), +(3,4,75,106,169,100,40,61), +(3,4,76,107,172,101,40,62), +(3,4,77,109,175,103,41,63), +(3,4,78,111,179,105,41,64), +(3,4,79,113,182,106,42,65), +(3,4,80,115,185,108,42,66), + +(3,5,1,22,16,23,21,22), +(3,5,2,22,16,23,22,23), +(3,5,3,22,16,24,24,25), +(3,5,4,22,17,24,25,26), +(3,5,5,23,17,24,26,27), +(3,5,6,23,17,25,28,29), +(3,5,7,23,17,25,29,30), +(3,5,8,23,18,26,30,32), +(3,5,9,23,18,26,32,33), +(3,5,10,23,18,26,33,35), +(3,5,11,24,18,27,35,36), +(3,5,12,24,19,27,36,38), +(3,5,13,24,19,28,37,39), +(3,5,14,24,19,28,39,41), +(3,5,15,24,19,28,40,42), +(3,5,16,24,20,29,42,44), +(3,5,17,25,20,29,43,45), +(3,5,18,25,20,30,45,47), +(3,5,19,25,21,30,46,49), +(3,5,20,25,21,31,48,50), +(3,5,21,25,21,31,50,52), +(3,5,22,26,22,31,51,53), +(3,5,23,26,22,32,53,55), +(3,5,24,26,22,32,54,57), +(3,5,25,26,22,33,56,58), +(3,5,26,27,23,33,58,60), +(3,5,27,27,23,34,59,62), +(3,5,28,27,23,34,61,64), +(3,5,29,27,24,35,63,65), +(3,5,30,28,24,35,64,67), +(3,5,31,28,24,36,66,69), +(3,5,32,28,25,36,68,71), +(3,5,33,28,25,37,70,72), +(3,5,34,29,26,38,71,74), +(3,5,35,29,26,38,73,76), +(3,5,36,29,26,39,75,78), +(3,5,37,29,27,39,77,80), +(3,5,38,30,27,40,78,82), +(3,5,39,30,27,40,80,84), +(3,5,40,30,28,41,82,86), +(3,5,41,31,28,41,84,88), +(3,5,42,31,29,42,86,89), +(3,5,43,31,29,43,88,91), +(3,5,44,32,29,43,90,93), +(3,5,45,32,30,44,92,95), +(3,5,46,32,30,44,93,97), +(3,5,47,32,30,45,95,99), +(3,5,48,33,31,46,97,101), +(3,5,49,33,31,46,99,103), +(3,5,50,33,32,47,101,106), +(3,5,51,34,32,48,103,108), +(3,5,52,34,33,48,105,110), +(3,5,53,35,33,49,107,112), +(3,5,54,35,33,50,109,114), +(3,5,55,35,34,50,111,116), +(3,5,56,36,34,51,113,118), +(3,5,57,36,35,52,116,120), +(3,5,58,36,35,52,118,123), +(3,5,59,37,36,53,120,125), +(3,5,60,37,36,54,122,127), +(3,5,61,37,37,54,124,129), +(3,5,62,38,37,55,126,131), +(3,5,63,38,38,56,128,134), +(3,5,64,39,38,57,131,136), +(3,5,65,39,39,57,133,138), +(3,5,66,39,39,58,135,141), +(3,5,67,40,40,59,137,143), +(3,5,68,40,40,59,139,145), +(3,5,69,41,40,60,142,148), +(3,5,70,41,41,61,144,150), +(3,5,71,41,42,62,147,153), +(3,5,72,42,42,62,150,163), +(3,5,73,42,43,63,153,166), +(3,5,74,43,43,64,155,170), +(3,5,75,43,44,65,158,173), +(3,5,76,43,45,66,161,176), +(3,5,77,44,45,67,164,179), +(3,5,78,44,46,68,167,182), +(3,5,79,45,46,69,170,184), +(3,5,80,45,47,70,173,189), + +(3,6,1,25,16,25,19,19), +(3,6,2,26,17,26,19,19), +(3,6,3,28,18,27,19,20), +(3,6,4,29,18,28,19,20), +(3,6,5,30,19,30,19,20), +(3,6,6,31,20,31,19,20), +(3,6,7,33,21,32,20,21), +(3,6,8,34,22,33,20,21), +(3,6,9,36,23,35,20,21), +(3,6,10,37,23,36,20,22), +(3,6,11,38,24,37,20,22), +(3,6,12,40,25,38,20,22), +(3,6,13,41,26,40,20,23), +(3,6,14,43,27,41,20,23), +(3,6,15,44,28,42,20,23), +(3,6,16,46,29,44,21,24), +(3,6,17,47,30,45,21,24), +(3,6,18,49,31,46,21,24), +(3,6,19,50,32,48,21,25), +(3,6,20,52,33,49,21,25), +(3,6,21,53,34,51,21,26), +(3,6,22,55,34,52,21,26), +(3,6,23,56,35,53,21,26), +(3,6,24,58,36,55,22,27), +(3,6,25,59,37,56,22,27), +(3,6,26,61,38,58,22,27), +(3,6,27,63,39,59,22,28), +(3,6,28,64,41,61,22,28), +(3,6,29,66,42,62,22,29), +(3,6,30,68,43,64,23,29), +(3,6,31,69,44,65,23,30), +(3,6,32,71,45,67,23,30), +(3,6,33,73,46,68,23,30), +(3,6,34,75,47,70,23,31), +(3,6,35,76,48,72,24,31), +(3,6,36,78,49,73,24,32), +(3,6,37,80,50,75,24,32), +(3,6,38,82,51,76,24,33), +(3,6,39,84,52,78,24,33), +(3,6,40,85,54,80,24,34), +(3,6,41,87,55,81,25,34), +(3,6,42,89,56,83,25,35), +(3,6,43,91,57,85,25,35), +(3,6,44,93,58,87,25,36), +(3,6,45,95,59,88,26,36), +(3,6,46,97,61,90,26,37), +(3,6,47,99,62,92,26,37), +(3,6,48,101,63,94,26,38), +(3,6,49,102,64,95,26,38), +(3,6,50,104,65,97,27,39), +(3,6,51,106,67,99,27,39), +(3,6,52,108,68,99,27,40), +(3,6,53,109,68,101,27,40), +(3,6,54,110,69,101,28,41), +(3,6,55,110,69,102,28,41), +(3,6,56,113,71,105,28,42), +(3,6,57,118,72,107,28,42), +(3,6,58,120,73,109,29,43), +(3,6,59,123,75,111,29,43), +(3,6,60,125,76,113,29,44), +(3,6,61,126,77,115,29,45), +(3,6,62,127,79,117,29,45), +(3,6,63,129,80,120,30,46), +(3,6,64,132,82,122,30,46), +(3,6,65,135,83,124,30,47), +(3,6,66,137,85,127,30,48), +(3,6,67,144,86,129,31,48), +(3,6,68,146,88,131,31,49), +(3,6,69,149,89,133,31,50), +(3,6,70,152,91,136,31,50), +(3,6,71,154,93,139,32,51), +(3,6,72,157,94,141,32,52), +(3,6,73,160,96,144,32,53), +(3,6,74,163,98,146,32,53), +(3,6,75,166,99,150,33,54), +(3,6,76,169,101,152,33,55), +(3,6,77,172,103,155,33,56), +(3,6,78,176,104,157,33,56), +(3,6,79,179,106,160,34,57), +(3,6,80,182,108,163,34,58), + +(4,1,1,20,25,21,20,20), +(4,1,2,21,26,22,20,20), +(4,1,3,23,27,23,20,21), +(4,1,4,24,27,25,20,21), +(4,1,5,25,28,26,20,21), +(4,1,6,27,29,27,20,21), +(4,1,7,28,30,28,21,22), +(4,1,8,29,31,29,21,22), +(4,1,9,31,31,31,21,22), +(4,1,10,32,32,32,21,23), +(4,1,11,33,33,33,21,23), +(4,1,12,35,34,34,21,23), +(4,1,13,36,35,36,21,24), +(4,1,14,38,36,37,21,24), +(4,1,15,39,37,38,21,24), +(4,1,16,41,37,40,21,25), +(4,1,17,42,38,41,22,25), +(4,1,18,44,39,43,22,25), +(4,1,19,45,40,44,22,26), +(4,1,20,47,41,45,22,26), +(4,1,21,48,42,47,22,26), +(4,1,22,50,43,48,22,27), +(4,1,23,52,44,50,22,27), +(4,1,24,53,45,51,23,28), +(4,1,25,55,46,52,23,28), +(4,1,26,56,47,54,23,28), +(4,1,27,58,48,55,23,29), +(4,1,28,60,49,57,23,29), +(4,1,29,61,50,58,23,30), +(4,1,30,63,51,60,24,30), +(4,1,31,65,52,62,24,30), +(4,1,32,66,53,63,24,31), +(4,1,33,68,54,65,24,31), +(4,1,34,70,55,66,24,32), +(4,1,35,72,56,68,24,32), +(4,1,36,73,58,69,25,33), +(4,1,37,75,59,71,25,33), +(4,1,38,77,60,73,25,34), +(4,1,39,79,61,74,25,34), +(4,1,40,81,62,76,25,35), +(4,1,41,82,63,78,26,35), +(4,1,42,84,64,79,26,35), +(4,1,43,86,66,81,26,36), +(4,1,44,88,67,83,26,36), +(4,1,45,90,68,85,26,37), +(4,1,46,92,69,86,27,37), +(4,1,47,94,70,88,27,38), +(4,1,48,96,72,90,27,38), +(4,1,49,98,73,92,27,39), +(4,1,50,100,74,93,28,40), +(4,1,51,102,75,95,28,40), +(4,1,52,104,77,97,28,41), +(4,1,53,106,78,99,28,41), +(4,1,54,108,79,101,29,42), +(4,1,55,110,80,103,29,42), +(4,1,56,112,82,104,29,43), +(4,1,57,114,83,106,29,43), +(4,1,58,116,84,108,30,44), +(4,1,59,118,86,110,30,44), +(4,1,60,120,87,112,30,45), +(4,1,61,122,88,114,30,46), +(4,1,62,124,90,116,31,46), +(4,1,63,127,91,118,31,47), +(4,1,64,129,92,120,31,47), +(4,1,65,131,94,122,32,48), +(4,1,66,133,95,124,32,49), +(4,1,67,135,97,126,32,49), +(4,1,68,138,98,128,32,50), +(4,1,69,140,100,130,33,50), +(4,1,70,142,101,132,33,51), +(4,1,71,145,102,134,33,52), +(4,1,72,147,104,137,33,53), +(4,1,73,150,106,139,33,54), +(4,1,74,153,107,142,34,54), +(4,1,75,156,109,144,34,55), +(4,1,76,159,111,148,34,56), +(4,1,77,162,113,150,35,57), +(4,1,78,165,114,152,35,57), +(4,1,79,178,116,164,35,58), +(4,1,80,181,118,167,36,59), + +(4,3,1,17,28,20,20,21), +(4,3,2,17,29,21,21,22), +(4,3,3,18,31,22,21,22), +(4,3,4,18,32,23,22,23), +(4,3,5,19,33,24,22,24), +(4,3,6,19,35,25,23,24), +(4,3,7,20,36,26,24,25), +(4,3,8,20,38,27,24,25), +(4,3,9,21,39,27,25,26), +(4,3,10,21,40,28,25,27), +(4,3,11,22,42,29,26,28), +(4,3,12,22,43,30,27,28), +(4,3,13,23,45,31,27,29), +(4,3,14,23,46,32,28,30), +(4,3,15,24,48,34,29,30), +(4,3,16,24,50,35,29,31), +(4,3,17,25,51,36,30,32), +(4,3,18,25,53,37,31,33), +(4,3,19,26,54,38,31,33), +(4,3,20,26,56,39,32,34), +(4,3,21,27,57,40,33,35), +(4,3,22,27,59,41,33,36), +(4,3,23,28,61,42,34,36), +(4,3,24,28,62,43,35,37), +(4,3,25,29,64,44,36,38), +(4,3,26,30,66,46,36,39), +(4,3,27,30,68,47,37,40), +(4,3,28,31,69,48,38,41), +(4,3,29,31,71,49,39,41), +(4,3,30,32,73,50,39,42), +(4,3,31,33,75,52,40,43), +(4,3,32,33,76,53,41,44), +(4,3,33,34,78,54,42,45), +(4,3,34,34,80,55,43,46), +(4,3,35,35,82,57,44,47), +(4,3,36,36,84,58,44,48), +(4,3,37,36,86,59,45,48), +(4,3,38,37,87,60,46,49), +(4,3,39,38,89,62,47,50), +(4,3,40,38,91,63,48,51), +(4,3,41,39,93,64,49,52), +(4,3,42,40,95,66,49,53), +(4,3,43,40,97,67,50,54), +(4,3,44,41,99,68,51,55), +(4,3,45,42,101,70,52,56), +(4,3,46,42,103,71,53,57), +(4,3,47,43,105,72,54,58), +(4,3,48,44,107,74,55,59), +(4,3,49,45,109,75,56,60), +(4,3,50,45,111,77,57,61), +(4,3,51,46,113,78,58,62), +(4,3,52,47,115,79,59,63), +(4,3,53,47,118,81,60,64), +(4,3,54,48,120,82,61,65), +(4,3,55,49,122,84,61,66), +(4,3,56,50,124,85,62,67), +(4,3,57,50,126,87,63,68), +(4,3,58,51,128,88,64,69), +(4,3,59,52,131,90,65,70), +(4,3,60,53,133,91,66,72), +(4,3,61,54,135,93,67,73), +(4,3,62,54,137,94,69,74), +(4,3,63,55,140,96,70,75), +(4,3,64,56,142,97,71,76), +(4,3,65,57,144,99,72,77), +(4,3,66,58,147,101,73,78), +(4,3,67,58,149,102,74,79), +(4,3,68,59,151,104,75,81), +(4,3,69,60,154,105,76,82), +(4,3,70,61,156,107,77,83), +(4,3,71,62,159,109,78,84), +(4,3,72,63,162,111,79,85), +(4,3,73,64,165,113,80,87), +(4,3,74,65,168,115,82,88), +(4,3,75,66,171,117,83,90), +(4,3,76,67,174,119,84,91), +(4,3,77,68,177,121,86,93), +(4,3,78,69,180,123,87,94), +(4,3,79,70,190,125,91,96), +(4,3,80,71,193,127,93,97), + +(4,4,1,18,28,20,20,20), +(4,4,2,19,29,21,20,20), +(4,4,3,20,31,21,20,21), +(4,4,4,20,32,22,20,21), +(4,4,5,21,34,23,21,21), +(4,4,6,22,35,24,21,22), +(4,4,7,23,37,24,21,22), +(4,4,8,24,38,25,21,23), +(4,4,9,24,40,26,21,23), +(4,4,10,25,41,26,21,23), +(4,4,11,26,43,27,22,24), +(4,4,12,27,44,28,22,24), +(4,4,13,28,46,29,22,25), +(4,4,14,29,48,30,22,25), +(4,4,15,29,49,30,22,25), +(4,4,16,30,51,31,23,26), +(4,4,17,31,52,32,23,26), +(4,4,18,32,54,33,23,27), +(4,4,19,33,56,34,23,27), +(4,4,20,34,57,35,23,28), +(4,4,21,35,59,35,24,28), +(4,4,22,36,61,36,24,29), +(4,4,23,37,63,37,24,29), +(4,4,24,38,64,38,24,30), +(4,4,25,39,66,39,25,30), +(4,4,26,40,68,40,25,31), +(4,4,27,41,70,41,25,31), +(4,4,28,42,72,42,25,32), +(4,4,29,43,73,43,25,32), +(4,4,30,44,75,43,26,33), +(4,4,31,45,77,44,26,33), +(4,4,32,46,79,45,26,34), +(4,4,33,47,81,46,27,34), +(4,4,34,48,83,47,27,35), +(4,4,35,49,85,48,27,35), +(4,4,36,50,87,49,27,36), +(4,4,37,51,89,50,28,36), +(4,4,38,52,91,51,28,37), +(4,4,39,53,93,52,28,38), +(4,4,40,54,95,53,28,38), +(4,4,41,56,97,54,29,39), +(4,4,42,57,99,55,29,39), +(4,4,43,58,101,56,29,40), +(4,4,44,59,103,57,30,40), +(4,4,45,60,105,59,30,41), +(4,4,46,61,107,60,30,42), +(4,4,47,62,109,61,31,42), +(4,4,48,64,112,62,31,43), +(4,4,49,65,114,63,31,44), +(4,4,50,66,116,64,32,44), +(4,4,51,67,118,65,32,45), +(4,4,52,68,120,66,32,45), +(4,4,53,70,123,67,33,46), +(4,4,54,71,125,69,33,47), +(4,4,55,72,127,70,33,47), +(4,4,56,73,129,71,34,48), +(4,4,57,75,132,72,34,49), +(4,4,58,76,134,73,34,49), +(4,4,59,77,136,74,35,50), +(4,4,60,79,139,76,35,51), +(4,4,61,80,141,77,35,51), +(4,4,62,81,143,78,36,52), +(4,4,63,82,146,79,36,53), +(4,4,64,84,148,80,37,54), +(4,4,65,85,151,82,37,54), +(4,4,66,87,153,83,37,55), +(4,4,67,88,156,84,38,56), +(4,4,68,89,158,85,38,57), +(4,4,69,91,160,87,39,57), +(4,4,70,92,163,88,39,58), +(4,4,71,94,166,90,39,59), +(4,4,72,96,169,91,40,59), +(4,4,73,97,172,93,40,60), +(4,4,74,99,175,94,41,61), +(4,4,75,101,178,96,41,62), +(4,4,76,102,181,97,41,63), +(4,4,77,104,184,99,42,64), +(4,4,78,106,188,101,42,65), +(4,4,79,108,191,102,43,66), +(4,4,80,110,194,104,43,67), + +(4,5,1,17,25,19,22,23), +(4,5,2,17,25,19,23,24), +(4,5,3,17,25,20,25,26), +(4,5,4,17,26,20,26,27), +(4,5,5,18,26,20,27,28), +(4,5,6,18,26,21,29,30), +(4,5,7,18,26,21,30,31), +(4,5,8,18,26,22,31,33), +(4,5,9,18,27,22,33,34), +(4,5,10,19,27,22,34,36), +(4,5,11,19,27,23,36,37), +(4,5,12,19,27,23,37,39), +(4,5,13,19,28,24,38,40), +(4,5,14,19,28,24,40,42), +(4,5,15,19,28,25,41,43), +(4,5,16,20,28,25,43,45), +(4,5,17,20,29,25,44,46), +(4,5,18,20,29,26,46,48), +(4,5,19,20,29,26,47,49), +(4,5,20,21,30,27,49,51), +(4,5,21,21,30,27,51,53), +(4,5,22,21,30,28,52,54), +(4,5,23,21,30,28,54,56), +(4,5,24,21,31,29,55,58), +(4,5,25,22,31,29,57,59), +(4,5,26,22,31,30,59,61), +(4,5,27,22,32,30,60,63), +(4,5,28,22,32,31,62,65), +(4,5,29,23,32,31,64,66), +(4,5,30,23,33,32,65,68), +(4,5,31,23,33,32,67,70), +(4,5,32,23,33,33,69,72), +(4,5,33,24,34,33,70,73), +(4,5,34,24,34,34,72,75), +(4,5,35,24,34,34,74,77), +(4,5,36,24,35,35,76,79), +(4,5,37,25,35,35,78,81), +(4,5,38,25,35,36,79,83), +(4,5,39,25,36,37,81,85), +(4,5,40,26,36,37,83,87), +(4,5,41,26,37,38,85,88), +(4,5,42,26,37,38,87,90), +(4,5,43,27,37,39,89,92), +(4,5,44,27,38,39,91,94), +(4,5,45,27,38,40,92,96), +(4,5,46,27,39,41,94,98), +(4,5,47,28,39,41,96,100), +(4,5,48,28,39,42,98,102), +(4,5,49,28,40,43,100,104), +(4,5,50,29,40,43,102,106), +(4,5,51,29,41,44,104,109), +(4,5,52,29,41,44,106,111), +(4,5,53,30,42,45,108,113), +(4,5,54,30,42,46,110,115), +(4,5,55,30,43,46,112,117), +(4,5,56,31,43,47,114,119), +(4,5,57,31,43,48,117,121), +(4,5,58,31,44,48,119,124), +(4,5,59,32,44,49,121,126), +(4,5,60,32,45,50,123,128), +(4,5,61,33,45,51,125,130), +(4,5,62,33,46,51,127,132), +(4,5,63,33,46,52,129,135), +(4,5,64,34,47,53,132,137), +(4,5,65,34,47,53,134,139), +(4,5,66,34,48,54,136,142), +(4,5,67,35,48,55,138,144), +(4,5,68,35,49,56,140,146), +(4,5,69,36,49,56,143,149), +(4,5,70,36,50,57,145,151), +(4,5,71,36,51,58,148,161), +(4,5,72,37,51,58,151,164), +(4,5,73,37,52,59,154,168), +(4,5,74,38,52,60,156,171), +(4,5,75,38,53,61,159,174), +(4,5,76,38,54,62,162,177), +(4,5,77,39,54,63,165,180), +(4,5,78,39,55,64,168,183), +(4,5,79,40,55,65,171,186), +(4,5,80,40,56,66,200,191), + +(4,6,1,20,25,21,20,20), +(4,6,2,21,26,22,20,20), +(4,6,3,23,27,23,20,21), +(4,6,4,24,27,25,20,21), +(4,6,5,25,28,26,20,21), +(4,6,6,27,29,27,20,21), +(4,6,7,28,30,28,21,22), +(4,6,8,29,31,29,21,22), +(4,6,9,31,31,31,21,22), +(4,6,10,32,32,32,21,23), +(4,6,11,33,33,33,21,23), +(4,6,12,35,34,34,21,23), +(4,6,13,36,35,36,21,24), +(4,6,14,38,36,37,21,24), +(4,6,15,39,37,38,21,24), +(4,6,16,41,37,40,21,25), +(4,6,17,42,38,41,22,25), +(4,6,18,44,39,43,22,25), +(4,6,19,45,40,44,22,26), +(4,6,20,47,41,45,22,26), +(4,6,21,48,42,47,22,26), +(4,6,22,50,43,48,22,27), +(4,6,23,52,44,50,22,27), +(4,6,24,53,45,51,23,28), +(4,6,25,55,46,52,23,28), +(4,6,26,56,47,54,23,28), +(4,6,27,58,48,55,23,29), +(4,6,28,60,49,57,23,29), +(4,6,29,61,50,58,23,30), +(4,6,30,63,51,60,24,30), +(4,6,31,65,52,62,24,30), +(4,6,32,66,53,63,24,31), +(4,6,33,68,54,65,24,31), +(4,6,34,70,55,66,24,32), +(4,6,35,72,56,68,24,32), +(4,6,36,73,58,69,25,33), +(4,6,37,75,59,71,25,33), +(4,6,38,77,60,73,25,34), +(4,6,39,79,61,74,25,34), +(4,6,40,81,62,76,25,35), +(4,6,41,82,63,78,26,35), +(4,6,42,84,64,79,26,35), +(4,6,43,86,66,81,26,36), +(4,6,44,88,67,83,26,36), +(4,6,45,90,68,85,26,37), +(4,6,46,92,69,86,27,37), +(4,6,47,94,70,88,27,38), +(4,6,48,96,72,90,27,38), +(4,6,49,98,73,92,27,39), +(4,6,50,100,74,93,28,40), +(4,6,51,101,75,94,28,40), +(4,6,52,102,76,95,28,41), +(4,6,53,103,77,96,28,41), +(4,6,54,104,77,97,29,42), +(4,6,55,105,78,98,29,42), +(4,6,56,108,80,101,29,43), +(4,6,57,113,81,103,29,43), +(4,6,58,115,82,105,30,44), +(4,6,59,115,84,107,30,44), +(4,6,60,120,85,109,30,45), +(4,6,61,122,86,111,30,46), +(4,6,62,122,88,113,30,46), +(4,6,63,127,89,116,31,47), +(4,6,64,127,91,118,31,47), +(4,6,65,133,92,120,31,48), +(4,6,66,135,94,123,31,49), +(4,6,67,136,95,125,32,49), +(4,6,68,137,97,127,32,50), +(4,6,69,140,98,130,32,51), +(4,6,70,147,100,132,32,51), +(4,6,71,154,102,135,33,52), +(4,6,72,156,103,137,33,53), +(4,6,73,157,105,140,33,54), +(4,6,74,158,107,142,33,54), +(4,6,75,161,108,145,34,55), +(4,6,76,164,110,148,34,56), +(4,6,77,167,112,150,34,57), +(4,6,78,170,113,153,34,57), +(4,6,79,172,115,156,35,58), +(4,6,80,177,117,159,35,59), + +(4,11,1,18,25,19,22,22), +(4,11,2,19,25,20,23,23), +(4,11,3,19,26,20,24,24), +(4,11,4,20,26,21,25,26), +(4,11,5,20,27,22,26,27), +(4,11,6,21,27,22,27,28), +(4,11,7,21,28,23,28,29), +(4,11,8,22,28,24,29,30), +(4,11,9,23,29,24,30,32), +(4,11,10,23,29,25,32,33), +(4,11,11,24,30,26,33,34), +(4,11,12,24,31,26,34,35), +(4,11,13,25,31,27,35,37), +(4,11,14,26,32,28,36,38), +(4,11,15,26,32,29,37,39), +(4,11,16,27,33,29,38,41), +(4,11,17,28,33,30,40,42), +(4,11,18,28,34,31,41,43), +(4,11,19,29,35,32,42,45), +(4,11,20,30,35,32,43,46), +(4,11,21,30,36,33,45,48), +(4,11,22,31,36,34,46,49), +(4,11,23,32,37,35,47,51), +(4,11,24,32,38,36,48,52), +(4,11,25,33,38,36,50,53), +(4,11,26,34,39,37,51,55), +(4,11,27,35,40,38,52,56), +(4,11,28,35,40,39,54,58), +(4,11,29,36,41,40,55,59), +(4,11,30,37,42,41,56,61), +(4,11,31,38,42,42,58,62), +(4,11,32,38,43,42,59,64), +(4,11,33,39,44,43,60,66), +(4,11,34,40,44,44,62,67), +(4,11,35,41,45,45,63,69), +(4,11,36,42,46,46,65,70), +(4,11,37,42,47,47,66,72), +(4,11,38,43,47,48,67,74), +(4,11,39,44,48,49,69,75), +(4,11,40,45,49,50,70,77), +(4,11,41,46,50,51,72,79), +(4,11,42,46,50,52,73,80), +(4,11,43,47,51,53,75,82), +(4,11,44,48,52,54,76,84), +(4,11,45,49,53,55,78,85), +(4,11,46,50,54,56,79,87), +(4,11,47,51,54,57,81,89), +(4,11,48,52,55,58,83,91), +(4,11,49,53,56,59,84,93), +(4,11,50,53,57,60,86,94), +(4,11,51,54,58,61,87,96), +(4,11,52,55,59,62,89,98), +(4,11,53,56,59,63,91,100), +(4,11,54,57,60,64,92,102), +(4,11,55,58,61,65,94,103), +(4,11,56,59,62,66,95,105), +(4,11,57,60,63,67,97,107), +(4,11,58,61,64,68,99,109), +(4,11,59,62,65,69,101,111), +(4,11,60,63,66,70,102,113), +(4,11,61,64,66,72,104,115), +(4,11,62,65,67,73,106,117), +(4,11,63,66,68,74,107,119), +(4,11,64,67,69,75,109,121), +(4,11,65,68,70,76,111,123), +(4,11,66,69,71,77,113,125), +(4,11,67,70,72,78,115,127), +(4,11,68,71,73,80,116,129), +(4,11,69,72,74,81,118,131), +(4,11,70,73,75,82,120,133), +(4,11,71,75,76,83,122,135), +(4,11,72,76,78,85,125,138), +(4,11,73,77,79,86,127,140), +(4,11,74,78,80,88,131,143), +(4,11,75,80,81,89,133,145), +(4,11,76,81,82,91,134,148), +(4,11,77,82,83,92,136,151), +(4,11,78,84,85,94,138,153), +(4,11,79,85,86,95,141,156), +(4,11,80,86,87,97,143,159), + +(5,1,1,22,18,23,18,25), +(5,1,2,23,19,24,18,25), +(5,1,3,25,20,25,18,26), +(5,1,4,26,20,26,18,26), +(5,1,5,27,21,28,18,26), +(5,1,6,29,22,29,18,26), +(5,1,7,30,23,30,19,27), +(5,1,8,31,24,31,19,27), +(5,1,9,33,25,33,19,27), +(5,1,10,34,25,34,19,28), +(5,1,11,35,26,35,19,28), +(5,1,12,37,27,36,19,28), +(5,1,13,38,28,38,19,28), +(5,1,14,40,29,39,19,29), +(5,1,15,41,30,40,19,29), +(5,1,16,43,31,42,20,29), +(5,1,17,44,32,43,20,30), +(5,1,18,46,33,44,20,30), +(5,1,19,47,34,46,20,31), +(5,1,20,49,34,47,20,31), +(5,1,21,50,35,49,20,31), +(5,1,22,52,36,50,20,32), +(5,1,23,53,37,51,21,32), +(5,1,24,55,38,53,21,32), +(5,1,25,57,39,54,21,33), +(5,1,26,58,40,56,21,33), +(5,1,27,60,41,57,21,34), +(5,1,28,62,42,59,21,34), +(5,1,29,63,43,60,21,34), +(5,1,30,65,44,62,22,35), +(5,1,31,67,46,63,22,35), +(5,1,32,68,47,65,22,36), +(5,1,33,70,48,67,22,36), +(5,1,34,72,49,68,22,36), +(5,1,35,74,50,70,23,37), +(5,1,36,75,51,71,23,37), +(5,1,37,77,52,73,23,38), +(5,1,38,79,53,75,23,38), +(5,1,39,81,54,76,23,39), +(5,1,40,83,55,78,24,39), +(5,1,41,84,57,80,24,40), +(5,1,42,86,58,81,24,40), +(5,1,43,88,59,83,24,41), +(5,1,44,90,60,85,24,41), +(5,1,45,92,61,86,25,42), +(5,1,46,94,62,88,25,42), +(5,1,47,96,64,90,25,43), +(5,1,48,98,65,92,25,43), +(5,1,49,100,66,93,25,44), +(5,1,50,102,67,95,26,44), +(5,1,51,104,69,97,26,45), +(5,1,52,106,70,99,26,45), +(5,1,53,108,71,101,26,46), +(5,1,54,110,72,103,27,46), +(5,1,55,112,74,104,27,47), +(5,1,56,114,75,106,27,48), +(5,1,57,116,76,108,27,48), +(5,1,58,118,78,110,28,49), +(5,1,59,120,79,112,28,49), +(5,1,60,122,80,114,28,50), +(5,1,61,124,82,116,28,50), +(5,1,62,126,83,118,29,51), +(5,1,63,128,84,120,29,52), +(5,1,64,131,86,122,29,52), +(5,1,65,133,87,124,30,53), +(5,1,66,135,88,126,30,53), +(5,1,67,137,90,128,30,54), +(5,1,68,139,91,130,30,55), +(5,1,69,142,93,132,31,55), +(5,1,70,144,94,134,31,56), +(5,1,71,147,95,136,31,57), +(5,1,72,150,97,139,31,58), +(5,1,73,152,99,141,31,59), +(5,1,74,155,100,144,32,59), +(5,1,75,158,102,146,32,60), +(5,1,76,163,104,149,32,61), +(5,1,77,167,106,152,33,62), +(5,1,78,167,107,154,33,62), +(5,1,79,170,109,157,33,63), +(5,1,80,173,111,160,34,64), + +(5,4,1,20,21,22,18,25), +(5,4,2,21,22,23,18,25), +(5,4,3,22,24,23,18,26), +(5,4,4,22,25,24,18,26), +(5,4,5,23,27,25,19,26), +(5,4,6,24,28,25,19,27), +(5,4,7,25,30,26,19,27), +(5,4,8,25,31,27,19,27), +(5,4,9,26,33,28,19,28), +(5,4,10,27,34,28,19,28), +(5,4,11,28,36,29,20,29), +(5,4,12,29,38,30,20,29), +(5,4,13,30,39,31,20,29), +(5,4,14,31,41,32,20,30), +(5,4,15,31,42,32,20,30), +(5,4,16,32,44,33,21,31), +(5,4,17,33,46,34,21,31), +(5,4,18,34,47,35,21,32), +(5,4,19,35,49,36,21,32), +(5,4,20,36,51,36,21,32), +(5,4,21,37,52,37,22,33), +(5,4,22,38,54,38,22,33), +(5,4,23,39,56,39,22,34), +(5,4,24,40,58,40,22,34), +(5,4,25,41,60,41,23,35), +(5,4,26,42,61,42,23,35), +(5,4,27,43,63,43,23,36), +(5,4,28,44,65,44,23,36), +(5,4,29,45,67,44,24,37), +(5,4,30,46,69,45,24,37), +(5,4,31,47,71,46,24,38), +(5,4,32,48,72,47,24,38), +(5,4,33,49,74,48,25,39), +(5,4,34,50,76,49,25,39), +(5,4,35,51,78,50,25,40), +(5,4,36,52,80,51,25,41), +(5,4,37,53,82,52,26,41), +(5,4,38,54,84,53,26,42), +(5,4,39,55,86,54,26,42), +(5,4,40,56,88,55,27,43), +(5,4,41,57,90,56,27,43), +(5,4,42,59,92,57,27,44), +(5,4,43,60,94,58,27,45), +(5,4,44,61,96,59,28,45), +(5,4,45,62,99,60,28,46), +(5,4,46,63,101,61,28,46), +(5,4,47,64,103,63,29,47), +(5,4,48,66,105,64,29,48), +(5,4,49,67,107,65,29,48), +(5,4,50,68,109,66,30,49), +(5,4,51,69,111,67,30,50), +(5,4,52,70,114,68,30,50), +(5,4,53,72,116,69,31,51), +(5,4,54,73,118,70,31,52), +(5,4,55,74,120,72,31,52), +(5,4,56,75,123,73,32,53), +(5,4,57,77,125,74,32,54), +(5,4,58,78,127,75,32,54), +(5,4,59,79,130,76,33,55), +(5,4,60,81,132,77,33,56), +(5,4,61,82,134,79,34,56), +(5,4,62,83,137,80,34,57), +(5,4,63,84,139,81,34,58), +(5,4,64,86,141,82,35,59), +(5,4,65,87,144,84,35,59), +(5,4,66,88,146,85,35,60), +(5,4,67,90,149,86,36,61), +(5,4,68,91,151,87,36,61), +(5,4,69,93,154,89,37,62), +(5,4,70,94,156,90,37,63), +(5,4,71,96,159,91,37,64), +(5,4,72,98,162,93,38,64), +(5,4,73,99,165,95,38,65), +(5,4,74,101,168,96,39,66), +(5,4,75,103,171,98,39,67), +(5,4,76,104,174,99,39,68), +(5,4,77,106,177,101,40,69), +(5,4,78,108,181,103,40,70), +(5,4,79,110,184,104,41,71), +(5,4,80,112,187,106,41,72), + +(5,5,1,19,18,21,20,28), +(5,5,2,19,18,21,21,29), +(5,5,3,19,18,22,23,31), +(5,5,4,19,19,22,24,32), +(5,5,5,20,19,22,25,33), +(5,5,6,20,19,23,27,35), +(5,5,7,20,19,23,28,36), +(5,5,8,20,20,24,29,38), +(5,5,9,20,20,24,31,39), +(5,5,10,20,20,24,32,40), +(5,5,11,21,20,25,34,42), +(5,5,12,21,21,25,35,43), +(5,5,13,21,21,26,37,45), +(5,5,14,21,21,26,38,46), +(5,5,15,21,21,26,39,48), +(5,5,16,22,22,27,41,50), +(5,5,17,22,22,27,42,51), +(5,5,18,22,22,28,44,53), +(5,5,19,22,23,28,46,54), +(5,5,20,22,23,29,47,56), +(5,5,21,23,23,29,49,57), +(5,5,22,23,23,30,50,59), +(5,5,23,23,24,30,52,61), +(5,5,24,23,24,31,53,62), +(5,5,25,24,24,31,55,64), +(5,5,26,24,25,32,57,66), +(5,5,27,24,25,32,58,68), +(5,5,28,24,25,33,60,69), +(5,5,29,25,26,33,62,71), +(5,5,30,25,26,34,63,73), +(5,5,31,25,26,34,65,75), +(5,5,32,25,27,35,67,76), +(5,5,33,26,27,35,69,78), +(5,5,34,26,27,36,70,80), +(5,5,35,26,28,36,72,82), +(5,5,36,26,28,37,74,84), +(5,5,37,27,28,37,76,86), +(5,5,38,27,29,38,77,87), +(5,5,39,27,29,38,79,89), +(5,5,40,28,30,39,81,91), +(5,5,41,28,30,40,83,93), +(5,5,42,28,30,40,85,95), +(5,5,43,28,31,41,87,97), +(5,5,44,29,31,41,89,99), +(5,5,45,29,32,42,91,101), +(5,5,46,29,32,43,92,103), +(5,5,47,30,32,43,94,105), +(5,5,48,30,33,44,96,107), +(5,5,49,30,33,44,98,109), +(5,5,50,31,34,45,100,111), +(5,5,51,31,34,46,102,113), +(5,5,52,31,35,46,104,115), +(5,5,53,32,35,47,106,118), +(5,5,54,32,35,48,108,120), +(5,5,55,32,36,48,110,122), +(5,5,56,33,36,49,113,124), +(5,5,57,33,37,50,115,126), +(5,5,58,33,37,50,117,128), +(5,5,59,34,38,51,119,131), +(5,5,60,34,38,52,121,133), +(5,5,61,34,39,52,123,135), +(5,5,62,35,39,53,125,137), +(5,5,63,35,40,54,127,140), +(5,5,64,36,40,55,130,142), +(5,5,65,36,41,55,132,144), +(5,5,66,36,41,56,134,147), +(5,5,67,37,41,57,136,149), +(5,5,68,37,42,58,138,151), +(5,5,69,38,42,58,141,154), +(5,5,70,38,43,59,143,156), +(5,5,71,38,44,60,146,159), +(5,5,72,39,44,60,149,162), +(5,5,73,39,45,61,152,165), +(5,5,74,40,45,62,157,168), +(5,5,75,40,46,63,157,171), +(5,5,76,40,47,64,160,174), +(5,5,77,41,47,65,163,177), +(5,5,78,41,48,66,166,180), +(5,5,79,42,48,67,169,183), +(5,5,80,42,49,68,172,186), + +(5,6,1,22,18,23,18,25), +(5,6,2,23,19,24,18,25), +(5,6,3,25,20,25,18,26), +(5,6,4,26,20,26,18,26), +(5,6,5,27,21,28,18,26), +(5,6,6,29,22,29,18,26), +(5,6,7,30,23,30,19,27), +(5,6,8,31,24,31,19,27), +(5,6,9,33,25,33,19,27), +(5,6,10,34,25,34,19,28), +(5,6,11,35,26,35,19,28), +(5,6,12,37,27,36,19,28), +(5,6,13,38,28,38,19,28), +(5,6,14,40,29,39,19,29), +(5,6,15,41,30,40,19,29), +(5,6,16,43,31,42,20,29), +(5,6,17,44,32,43,20,30), +(5,6,18,46,33,44,20,30), +(5,6,19,47,34,46,20,31), +(5,6,20,49,34,47,20,31), +(5,6,21,50,35,49,20,31), +(5,6,22,52,36,50,20,32), +(5,6,23,53,37,51,21,32), +(5,6,24,55,38,53,21,32), +(5,6,25,57,39,54,21,33), +(5,6,26,58,40,56,21,33), +(5,6,27,60,41,57,21,34), +(5,6,28,62,42,59,21,34), +(5,6,29,63,43,60,21,34), +(5,6,30,65,44,62,22,35), +(5,6,31,67,46,63,22,35), +(5,6,32,68,47,65,22,36), +(5,6,33,70,48,67,22,36), +(5,6,34,72,49,68,22,36), +(5,6,35,74,50,70,23,37), +(5,6,36,75,51,71,23,37), +(5,6,37,77,52,73,23,38), +(5,6,38,79,53,75,23,38), +(5,6,39,81,54,76,23,39), +(5,6,40,83,55,78,24,39), +(5,6,41,84,57,80,24,40), +(5,6,42,86,58,81,24,40), +(5,6,43,88,59,83,24,41), +(5,6,44,90,60,85,24,41), +(5,6,45,92,61,86,25,42), +(5,6,46,94,62,88,25,42), +(5,6,47,96,64,90,25,43), +(5,6,48,98,65,92,25,43), +(5,6,49,100,66,93,25,44), +(5,6,50,102,67,95,26,44), +(5,6,51,103,67,96,26,45), +(5,6,52,104,68,97,26,45), +(5,6,53,105,69,98,26,46), +(5,6,54,106,70,99,27,46), +(5,6,55,107,71,100,27,47), +(5,6,56,110,73,103,27,48), +(5,6,57,112,74,105,27,48), +(5,6,58,114,75,107,28,49), +(5,6,59,119,77,109,28,49), +(5,6,60,122,78,111,28,50), +(5,6,61,124,79,113,28,51), +(5,6,62,127,81,115,28,51), +(5,6,63,129,82,118,29,52), +(5,6,64,136,84,120,29,52), +(5,6,65,137,85,123,29,53), +(5,6,66,138,87,125,29,54), +(5,6,67,141,88,127,30,54), +(5,6,68,143,90,129,30,55), +(5,6,69,146,91,132,30,56), +(5,6,70,149,93,134,30,56), +(5,6,71,152,95,137,31,57), +(5,6,72,154,96,139,31,58), +(5,6,73,157,98,142,31,59), +(5,6,74,158,100,145,31,59), +(5,6,75,159,101,147,32,60), +(5,6,76,162,103,150,32,61), +(5,6,77,167,105,152,32,62), +(5,6,78,173,106,155,32,62), +(5,6,79,174,108,158,33,63), +(5,6,80,174,110,161,33,64), + +(5,8,1,19,18,21,21,27), +(5,8,2,19,18,21,22,28), +(5,8,3,19,18,22,24,30), +(5,8,4,19,18,22,25,31), +(5,8,5,19,19,22,26,32), +(5,8,6,19,19,22,28,34), +(5,8,7,20,19,23,29,35), +(5,8,8,20,19,23,31,36), +(5,8,9,20,19,23,32,38), +(5,8,10,20,19,24,34,39), +(5,8,11,20,20,24,35,40), +(5,8,12,20,20,24,37,42), +(5,8,13,20,20,25,38,43), +(5,8,14,20,20,25,40,45), +(5,8,15,20,20,25,41,46), +(5,8,16,21,21,26,43,48), +(5,8,17,21,21,26,44,49), +(5,8,18,21,21,26,46,51), +(5,8,19,21,21,27,48,52), +(5,8,20,21,21,27,49,54), +(5,8,21,21,22,27,51,55), +(5,8,22,21,22,28,52,57), +(5,8,23,21,22,28,54,58), +(5,8,24,22,22,29,56,60), +(5,8,25,22,23,29,57,62), +(5,8,26,22,23,29,59,63), +(5,8,27,22,23,30,61,65), +(5,8,28,22,23,30,63,67), +(5,8,29,22,24,31,64,68), +(5,8,30,23,24,31,66,70), +(5,8,31,23,24,31,68,72), +(5,8,32,23,24,32,70,73), +(5,8,33,23,25,32,72,75), +(5,8,34,23,25,33,73,77), +(5,8,35,24,25,33,75,79), +(5,8,36,24,25,34,77,80), +(5,8,37,24,26,34,79,82), +(5,8,38,24,26,35,81,84), +(5,8,39,24,26,35,83,86), +(5,8,40,24,27,35,85,88), +(5,8,41,25,27,36,87,90), +(5,8,42,25,27,36,89,91), +(5,8,43,25,27,37,90,93), +(5,8,44,25,28,37,92,95), +(5,8,45,26,28,38,94,97), +(5,8,46,26,28,38,96,99), +(5,8,47,26,29,39,98,101), +(5,8,48,26,29,39,100,103), +(5,8,49,26,29,40,103,105), +(5,8,50,27,30,40,105,107), +(5,8,51,27,30,41,107,109), +(5,8,52,27,30,42,109,111), +(5,8,53,27,31,42,111,113), +(5,8,54,28,31,43,113,115), +(5,8,55,28,31,43,115,117), +(5,8,56,28,32,44,117,119), +(5,8,57,28,32,44,119,121), +(5,8,58,29,32,45,122,123), +(5,8,59,29,33,45,124,126), +(5,8,60,29,33,46,126,128), +(5,8,61,29,34,47,128,130), +(5,8,62,30,34,47,131,132), +(5,8,63,30,34,48,133,134), +(5,8,64,30,35,48,135,136), +(5,8,65,31,35,49,137,139), +(5,8,66,31,35,50,140,141), +(5,8,67,31,36,50,142,143), +(5,8,68,31,36,51,144,145), +(5,8,69,32,37,51,147,148), +(5,8,70,32,37,52,149,150), +(5,8,71,32,37,53,152,153), +(5,8,72,32,38,54,155,156), +(5,8,73,32,38,55,158,159), +(5,8,74,33,39,55,161,161), +(5,8,75,33,39,56,164,164), +(5,8,76,33,39,57,167,167), +(5,8,77,34,40,58,170,170), +(5,8,78,34,40,58,173,173), +(5,8,79,34,41,59,176,176), +(5,8,80,35,41,60,179,179), + +(5,9,1,19,18,22,20,27), +(5,9,2,19,18,23,21,28), +(5,9,3,20,19,23,22,29), +(5,9,4,20,19,24,24,30), +(5,9,5,20,19,24,25,32), +(5,9,6,20,20,25,26,33), +(5,9,7,21,20,25,27,34), +(5,9,8,21,21,26,28,35), +(5,9,9,21,21,26,30,36), +(5,9,10,22,21,27,31,38), +(5,9,11,22,22,28,32,39), +(5,9,12,22,22,28,34,40), +(5,9,13,23,23,29,35,41), +(5,9,14,23,23,30,36,43), +(5,9,15,23,24,30,37,44), +(5,9,16,24,24,31,39,45), +(5,9,17,24,24,31,40,47), +(5,9,18,24,25,32,42,48), +(5,9,19,25,25,33,43,49), +(5,9,20,25,26,33,44,51), +(5,9,21,26,26,34,46,52), +(5,9,22,26,27,35,47,53), +(5,9,23,26,27,36,49,55), +(5,9,24,27,28,36,50,56), +(5,9,25,27,28,37,52,58), +(5,9,26,27,29,38,53,59), +(5,9,27,28,29,38,55,60), +(5,9,28,28,30,39,56,62), +(5,9,29,29,30,40,58,63), +(5,9,30,29,31,41,59,65), +(5,9,31,30,31,41,61,66), +(5,9,32,30,32,42,62,68), +(5,9,33,30,32,43,64,69), +(5,9,34,31,33,44,65,71), +(5,9,35,31,33,45,67,73), +(5,9,36,32,34,45,69,74), +(5,9,37,32,34,46,70,76), +(5,9,38,33,35,47,72,77), +(5,9,39,33,36,48,73,79), +(5,9,40,34,36,49,75,81), +(5,9,41,34,37,49,77,82), +(5,9,42,35,37,50,78,84), +(5,9,43,35,38,51,80,86), +(5,9,44,36,39,52,82,87), +(5,9,45,36,39,53,84,89), +(5,9,46,37,40,54,85,91), +(5,9,47,37,40,55,87,92), +(5,9,48,38,41,55,89,94), +(5,9,49,38,42,56,91,96), +(5,9,50,39,42,57,92,98), +(5,9,51,39,43,58,94,100), +(5,9,52,40,44,59,96,101), +(5,9,53,40,44,60,98,103), +(5,9,54,41,45,61,100,105), +(5,9,55,41,45,62,102,107), +(5,9,56,42,46,63,103,109), +(5,9,57,42,47,64,105,111), +(5,9,58,43,47,65,107,112), +(5,9,59,43,48,66,109,114), +(5,9,60,44,49,67,111,116), +(5,9,61,45,50,68,113,118), +(5,9,62,45,50,69,115,120), +(5,9,63,46,51,70,117,122), +(5,9,64,46,52,71,119,124), +(5,9,65,47,52,72,121,126), +(5,9,66,48,53,73,123,128), +(5,9,67,48,54,74,125,130), +(5,9,68,49,55,75,127,132), +(5,9,69,49,55,76,129,134), +(5,9,70,50,56,77,131,136), +(5,9,71,51,57,86,135,147), +(5,9,72,52,57,88,136,149), +(5,9,73,53,58,89,138,152), +(5,9,74,53,59,90,141,155), +(5,9,75,54,60,92,143,157), +(5,9,76,55,61,93,146,160), +(5,9,77,56,62,94,149,163), +(5,9,78,56,63,96,151,166), +(5,9,79,57,64,97,154,169), +(5,9,80,58,65,99,157,171), + +(6,1,1,28,15,24,15,22), +(6,1,2,29,16,25,15,22), +(6,1,3,31,17,26,15,23), +(6,1,4,32,17,27,15,23), +(6,1,5,33,18,29,15,23), +(6,1,6,34,19,30,15,23), +(6,1,7,36,20,31,16,24), +(6,1,8,37,21,32,16,24), +(6,1,9,38,22,34,16,24), +(6,1,10,40,22,35,16,25), +(6,1,11,41,23,36,16,25), +(6,1,12,43,24,37,16,25), +(6,1,13,44,25,39,16,26), +(6,1,14,46,26,40,16,26), +(6,1,15,47,27,41,17,26), +(6,1,16,48,28,43,17,27), +(6,1,17,50,29,44,17,27), +(6,1,18,51,30,45,17,27), +(6,1,19,53,31,47,17,28), +(6,1,20,54,32,48,17,28), +(6,1,21,56,33,50,17,28), +(6,1,22,58,34,51,18,29), +(6,1,23,59,35,52,18,29), +(6,1,24,61,36,54,18,30), +(6,1,25,62,37,55,18,30), +(6,1,26,64,38,57,18,30), +(6,1,27,66,39,58,18,31), +(6,1,28,67,40,60,18,31), +(6,1,29,69,41,61,19,32), +(6,1,30,71,42,63,19,32), +(6,1,31,72,43,64,19,32), +(6,1,32,74,44,66,19,33), +(6,1,33,76,45,67,19,33), +(6,1,34,77,46,69,20,34), +(6,1,35,79,47,71,20,34), +(6,1,36,81,48,72,20,35), +(6,1,37,83,49,74,20,35), +(6,1,38,85,50,76,20,35), +(6,1,39,86,51,77,21,36), +(6,1,40,88,53,79,21,36), +(6,1,41,90,54,81,21,37), +(6,1,42,92,55,82,21,37), +(6,1,43,94,56,84,21,38), +(6,1,44,96,57,86,22,38), +(6,1,45,98,58,87,22,39), +(6,1,46,99,60,89,22,39), +(6,1,47,101,61,91,22,40), +(6,1,48,103,62,93,22,40), +(6,1,49,105,63,94,23,41), +(6,1,50,107,65,96,23,41), +(6,1,51,109,66,98,23,42), +(6,1,52,111,67,100,23,42), +(6,1,53,113,68,102,24,43), +(6,1,54,115,70,104,24,44), +(6,1,55,117,71,105,24,44), +(6,1,56,119,72,107,24,45), +(6,1,57,122,73,109,25,45), +(6,1,58,124,75,111,25,46), +(6,1,59,126,76,113,25,46), +(6,1,60,128,77,115,25,47), +(6,1,61,130,79,117,26,48), +(6,1,62,132,80,119,26,48), +(6,1,63,134,81,121,26,49), +(6,1,64,137,83,123,26,49), +(6,1,65,139,84,125,27,50), +(6,1,66,141,85,127,27,51), +(6,1,67,143,87,129,27,51), +(6,1,68,145,88,131,27,52), +(6,1,69,148,90,133,28,52), +(6,1,70,150,91,135,28,53), +(6,1,71,153,92,137,28,54), +(6,1,72,155,94,140,28,55), +(6,1,73,158,96,142,28,56), +(6,1,74,161,97,145,29,56), +(6,1,75,164,99,147,29,57), +(6,1,76,167,101,150,29,58), +(6,1,77,170,103,153,30,59), +(6,1,78,173,104,155,30,59), +(6,1,79,176,106,164,30,60), +(6,1,80,179,108,170,31,61), + +(6,3,1,25,18,23,15,23), +(6,3,2,25,19,24,16,24), +(6,3,3,26,21,25,16,24), +(6,3,4,26,22,26,17,25), +(6,3,5,27,24,27,17,25), +(6,3,6,27,25,28,18,26), +(6,3,7,28,26,28,19,27), +(6,3,8,28,28,29,19,27), +(6,3,9,28,29,30,20,28), +(6,3,10,29,31,31,20,29), +(6,3,11,29,32,32,21,29), +(6,3,12,30,34,33,22,30), +(6,3,13,30,35,34,22,31), +(6,3,14,31,37,35,23,32), +(6,3,15,31,38,36,24,32), +(6,3,16,32,40,37,24,33), +(6,3,17,32,41,39,25,34), +(6,3,18,33,43,40,26,35), +(6,3,19,33,45,41,27,35), +(6,3,20,34,46,42,27,36), +(6,3,21,34,48,43,28,37), +(6,3,22,35,50,44,29,38), +(6,3,23,35,51,45,29,38), +(6,3,24,36,53,46,30,39), +(6,3,25,37,55,47,31,40), +(6,3,26,37,56,48,32,41), +(6,3,27,38,58,50,32,42), +(6,3,28,38,60,51,33,42), +(6,3,29,39,62,52,34,43), +(6,3,30,39,63,53,35,44), +(6,3,31,40,65,54,36,45), +(6,3,32,41,67,56,36,46), +(6,3,33,41,69,57,37,47), +(6,3,34,42,71,58,38,48), +(6,3,35,43,72,59,39,48), +(6,3,36,43,74,61,40,49), +(6,3,37,44,76,62,40,50), +(6,3,38,45,78,63,41,51), +(6,3,39,45,80,64,42,52), +(6,3,40,46,82,66,43,53), +(6,3,41,47,84,67,44,54), +(6,3,42,47,86,68,45,55), +(6,3,43,48,88,70,46,56), +(6,3,44,49,90,71,46,57), +(6,3,45,49,92,72,47,58), +(6,3,46,50,94,74,48,59), +(6,3,47,51,96,75,49,60), +(6,3,48,51,98,77,50,61), +(6,3,49,52,100,78,51,62), +(6,3,50,53,102,79,52,63), +(6,3,51,54,104,81,53,64), +(6,3,52,54,106,82,54,65), +(6,3,53,55,108,84,55,66), +(6,3,54,56,110,85,56,67), +(6,3,55,57,112,87,57,68), +(6,3,56,57,114,88,58,69), +(6,3,57,58,117,90,59,70), +(6,3,58,59,119,91,60,71), +(6,3,59,60,121,93,61,72), +(6,3,60,61,123,94,62,74), +(6,3,61,61,125,96,63,75), +(6,3,62,62,128,97,64,76), +(6,3,63,63,130,99,65,77), +(6,3,64,64,132,100,66,78), +(6,3,65,65,134,102,67,79), +(6,3,66,66,137,104,68,80), +(6,3,67,66,139,105,69,81), +(6,3,68,67,141,107,70,83), +(6,3,69,68,144,108,71,84), +(6,3,70,69,146,110,72,85), +(6,3,71,70,149,112,73,86), +(6,3,72,71,152,114,74,87), +(6,3,73,72,155,116,75,89), +(6,3,74,73,158,118,77,90), +(6,3,75,74,161,120,78,92), +(6,3,76,75,164,122,79,93), +(6,3,77,76,167,124,81,95), +(6,3,78,77,176,126,85,96), +(6,3,79,78,179,128,86,98), +(6,3,80,79,183,130,88,99), + +(6,6,1,28,15,24,15,22), +(6,6,2,29,16,25,15,22), +(6,6,3,31,17,26,15,23), +(6,6,4,32,17,27,15,23), +(6,6,5,33,18,29,15,23), +(6,6,6,34,19,30,15,23), +(6,6,7,36,20,31,16,24), +(6,6,8,37,21,32,16,24), +(6,6,9,38,22,34,16,24), +(6,6,10,40,22,35,16,25), +(6,6,11,41,23,36,16,25), +(6,6,12,43,24,37,16,25), +(6,6,13,44,25,39,16,26), +(6,6,14,46,26,40,16,26), +(6,6,15,47,27,41,17,26), +(6,6,16,48,28,43,17,27), +(6,6,17,50,29,44,17,27), +(6,6,18,51,30,45,17,27), +(6,6,19,53,31,47,17,28), +(6,6,20,54,32,48,17,28), +(6,6,21,56,33,50,17,28), +(6,6,22,58,34,51,18,29), +(6,6,23,59,35,52,18,29), +(6,6,24,61,36,54,18,30), +(6,6,25,62,37,55,18,30), +(6,6,26,64,38,57,18,30), +(6,6,27,66,39,58,18,31), +(6,6,28,67,40,60,18,31), +(6,6,29,69,41,61,19,32), +(6,6,30,71,42,63,19,32), +(6,6,31,72,43,64,19,32), +(6,6,32,74,44,66,19,33), +(6,6,33,76,45,67,19,33), +(6,6,34,77,46,69,20,34), +(6,6,35,79,47,71,20,34), +(6,6,36,81,48,72,20,35), +(6,6,37,83,49,74,20,35), +(6,6,38,85,50,76,20,35), +(6,6,39,86,51,77,21,36), +(6,6,40,88,53,79,21,36), +(6,6,41,90,54,81,21,37), +(6,6,42,92,55,82,21,37), +(6,6,43,94,56,84,21,38), +(6,6,44,96,57,86,22,38), +(6,6,45,98,58,87,22,39), +(6,6,46,99,60,89,22,39), +(6,6,47,101,60,91,22,40), +(6,6,48,103,61,93,22,40), +(6,6,49,105,62,94,23,41), +(6,6,50,107,63,96,23,41), +(6,6,51,109,64,97,23,42), +(6,6,52,110,65,98,23,42), +(6,6,53,111,66,99,24,43), +(6,6,54,112,67,100,24,44), +(6,6,55,113,68,101,24,44), +(6,6,56,116,70,104,24,45), +(6,6,57,121,71,106,24,45), +(6,6,58,123,72,108,25,46), +(6,6,59,123,74,110,25,46), +(6,6,60,125,75,112,25,47), +(6,6,61,127,76,114,25,48), +(6,6,62,133,78,116,25,48), +(6,6,63,135,79,119,26,49), +(6,6,64,139,81,121,26,49), +(6,6,65,142,82,123,26,50), +(6,6,66,146,84,126,26,51), +(6,6,67,150,85,132,27,51), +(6,6,68,153,87,137,27,52), +(6,6,69,157,88,140,27,53), +(6,6,70,160,90,143,27,53), +(6,6,71,163,92,146,28,54), +(6,6,72,165,93,148,28,55), +(6,6,73,167,95,150,28,56), +(6,6,74,171,97,153,28,56), +(6,6,75,174,98,156,29,57), +(6,6,76,178,100,156,29,58), +(6,6,77,179,102,156,29,59), +(6,6,78,179,103,156,29,59), +(6,6,79,182,105,159,30,60), +(6,6,80,185,107,162,30,61), + +(6,7,1,26,15,23,16,24), +(6,7,2,27,15,24,17,25), +(6,7,3,28,16,25,18,26), +(6,7,4,28,16,26,19,27), +(6,7,5,29,17,27,20,28), +(6,7,6,30,17,28,21,29), +(6,7,7,31,18,29,22,30), +(6,7,8,32,18,30,23,31), +(6,7,9,33,19,31,24,32), +(6,7,10,34,19,32,25,33), +(6,7,11,35,20,33,26,35), +(6,7,12,35,20,34,27,36), +(6,7,13,36,21,35,28,37), +(6,7,14,37,21,36,29,38), +(6,7,15,38,22,37,30,39), +(6,7,16,39,22,39,31,40), +(6,7,17,40,23,40,32,42), +(6,7,18,41,23,41,33,43), +(6,7,19,42,24,42,34,44), +(6,7,20,43,24,43,35,45), +(6,7,21,44,25,44,36,46), +(6,7,22,45,25,45,37,48), +(6,7,23,46,26,47,38,49), +(6,7,24,47,27,48,40,50), +(6,7,25,48,27,49,41,51), +(6,7,26,49,28,50,42,53), +(6,7,27,51,28,52,43,54), +(6,7,28,52,29,53,44,55), +(6,7,29,53,29,54,45,57), +(6,7,30,54,30,55,47,58), +(6,7,31,55,31,57,48,59), +(6,7,32,56,31,58,49,61), +(6,7,33,57,32,59,50,62), +(6,7,34,58,33,61,51,64), +(6,7,35,60,33,62,53,65), +(6,7,36,61,34,63,54,66), +(6,7,37,62,34,65,55,68), +(6,7,38,63,35,66,57,69), +(6,7,39,64,36,67,58,71), +(6,7,40,66,36,69,59,72), +(6,7,41,67,37,70,60,74), +(6,7,42,68,38,72,62,75), +(6,7,43,69,38,73,63,77), +(6,7,44,70,39,74,64,78), +(6,7,45,72,40,76,66,80), +(6,7,46,73,41,77,67,81), +(6,7,47,74,41,79,69,83), +(6,7,48,76,42,80,70,84), +(6,7,49,77,43,82,71,86), +(6,7,50,78,43,83,73,88), +(6,7,51,80,44,85,74,89), +(6,7,52,81,45,86,76,91), +(6,7,53,82,46,88,77,92), +(6,7,54,84,46,90,78,94), +(6,7,55,85,47,91,80,96), +(6,7,56,86,48,93,81,97), +(6,7,57,88,49,94,83,99), +(6,7,58,89,49,96,84,101), +(6,7,59,91,50,97,86,102), +(6,7,60,92,51,99,87,104), +(6,7,61,94,52,101,89,106), +(6,7,62,95,52,102,90,108), +(6,7,63,96,53,104,92,109), +(6,7,64,98,54,106,93,111), +(6,7,65,99,55,107,95,113), +(6,7,66,101,56,109,97,115), +(6,7,67,102,57,111,98,117), +(6,7,68,104,57,113,100,118), +(6,7,69,105,58,114,101,120), +(6,7,70,107,59,116,103,122), +(6,7,71,108,60,118,113,124), +(6,7,72,110,61,120,117,127), +(6,7,73,112,62,122,119,129), +(6,7,74,114,63,125,122,131), +(6,7,75,116,64,127,124,133), +(6,7,76,118,65,129,126,136), +(6,7,77,119,66,131,128,138), +(6,7,78,121,67,133,130,140), +(6,7,79,123,68,136,133,143), +(6,7,80,125,69,138,135,145), + +(6,11,1,26,15,22,17,24), +(6,11,2,27,16,23,18,25), +(6,11,3,27,16,23,19,26), +(6,11,4,28,17,24,20,27), +(6,11,5,28,17,25,21,29), +(6,11,6,29,18,25,22,30), +(6,11,7,29,18,26,23,31), +(6,11,8,30,19,27,24,32), +(6,11,9,30,19,27,26,34), +(6,11,10,31,20,28,27,35), +(6,11,11,32,20,29,28,36), +(6,11,12,32,21,29,29,37), +(6,11,13,33,21,30,30,39), +(6,11,14,33,22,31,31,40), +(6,11,15,34,23,32,32,41), +(6,11,16,35,23,32,34,43), +(6,11,17,35,24,33,35,44), +(6,11,18,36,24,34,36,45), +(6,11,19,37,25,35,37,47), +(6,11,20,37,26,35,39,48), +(6,11,21,38,26,36,40,50), +(6,11,22,39,27,37,41,51), +(6,11,23,39,28,38,42,52), +(6,11,24,40,28,39,44,54), +(6,11,25,41,29,39,45,55), +(6,11,26,41,30,40,46,57), +(6,11,27,42,30,41,47,58), +(6,11,28,43,31,42,49,60), +(6,11,29,44,32,43,50,61), +(6,11,30,44,32,44,52,63), +(6,11,31,45,33,44,53,64), +(6,11,32,46,34,45,54,66), +(6,11,33,47,34,46,56,67), +(6,11,34,47,35,47,57,69), +(6,11,35,48,36,48,58,71), +(6,11,36,49,36,49,60,72), +(6,11,37,50,37,50,61,74), +(6,11,38,51,38,51,63,76), +(6,11,39,52,39,52,64,77), +(6,11,40,52,39,53,66,79), +(6,11,41,53,40,54,67,81), +(6,11,42,54,41,55,69,82), +(6,11,43,55,42,56,70,84), +(6,11,44,56,43,57,72,86), +(6,11,45,57,43,57,73,87), +(6,11,46,57,44,58,75,89), +(6,11,47,58,45,60,76,91), +(6,11,48,59,46,61,78,93), +(6,11,49,60,47,62,79,94), +(6,11,50,61,47,63,81,96), +(6,11,51,62,48,64,83,98), +(6,11,52,63,49,65,84,100), +(6,11,53,64,50,66,86,102), +(6,11,54,65,51,67,87,104), +(6,11,55,66,51,68,89,105), +(6,11,56,67,52,69,91,107), +(6,11,57,68,53,70,92,109), +(6,11,58,69,54,71,94,111), +(6,11,59,70,55,72,96,113), +(6,11,60,71,56,73,97,115), +(6,11,61,72,57,74,99,117), +(6,11,62,73,58,76,101,119), +(6,11,63,74,59,77,103,121), +(6,11,64,75,59,78,104,123), +(6,11,65,76,60,79,106,125), +(6,11,66,77,61,80,108,127), +(6,11,67,78,62,81,110,129), +(6,11,68,79,63,83,111,131), +(6,11,69,80,64,84,113,133), +(6,11,70,81,65,85,115,135), +(6,11,71,83,66,86,117,137), +(6,11,72,84,68,88,120,140), +(6,11,73,85,69,89,122,142), +(6,11,74,86,70,91,124,145), +(6,11,75,88,71,92,126,147), +(6,11,76,89,72,94,128,150), +(6,11,77,90,73,95,131,153), +(6,11,78,92,75,97,133,155), +(6,11,79,93,76,98,136,158), +(6,11,80,94,77,100,138,185), + +(7,1,1,18,23,21,24,20), +(7,1,2,19,24,22,24,20), +(7,1,3,21,25,23,24,21), +(7,1,4,22,25,25,24,21), +(7,1,5,23,26,26,24,21), +(7,1,6,25,27,27,24,21), +(7,1,7,26,28,28,24,22), +(7,1,8,27,29,29,25,22), +(7,1,9,29,29,31,25,22), +(7,1,10,30,30,32,25,23), +(7,1,11,32,31,33,25,23), +(7,1,12,33,32,34,25,23), +(7,1,13,34,33,36,25,24), +(7,1,14,36,34,37,25,24), +(7,1,15,37,35,38,25,24), +(7,1,16,39,36,40,25,25), +(7,1,17,40,36,41,25,25), +(7,1,18,42,37,43,26,25), +(7,1,19,43,38,44,26,26), +(7,1,20,45,39,45,26,26), +(7,1,21,47,40,47,26,26), +(7,1,22,48,41,48,26,27), +(7,1,23,50,42,50,26,27), +(7,1,24,51,43,51,26,28), +(7,1,25,53,44,52,27,28), +(7,1,26,55,45,54,27,28), +(7,1,27,56,46,55,27,29), +(7,1,28,58,47,57,27,29), +(7,1,29,59,48,58,27,30), +(7,1,30,61,49,60,27,30), +(7,1,31,63,50,62,27,30), +(7,1,32,65,51,63,28,31), +(7,1,33,66,52,65,28,31), +(7,1,34,68,53,66,28,32), +(7,1,35,70,55,68,28,32), +(7,1,36,72,56,69,28,33), +(7,1,37,73,57,71,29,33), +(7,1,38,75,58,73,29,34), +(7,1,39,77,59,74,29,34), +(7,1,40,79,60,76,29,35), +(7,1,41,81,61,78,29,35), +(7,1,42,82,62,79,30,35), +(7,1,43,84,64,81,30,36), +(7,1,44,86,65,83,30,36), +(7,1,45,88,66,85,30,37), +(7,1,46,90,67,86,30,37), +(7,1,47,92,68,88,31,38), +(7,1,48,94,70,90,31,38), +(7,1,49,96,71,92,31,39), +(7,1,50,98,72,93,31,40), +(7,1,51,100,73,95,32,40), +(7,1,52,102,75,97,32,41), +(7,1,53,104,76,99,32,41), +(7,1,54,106,77,101,32,42), +(7,1,55,108,78,103,33,42), +(7,1,56,110,80,104,33,43), +(7,1,57,112,81,106,33,43), +(7,1,58,114,82,108,33,44), +(7,1,59,116,84,110,34,44), +(7,1,60,118,85,112,34,45), +(7,1,61,120,86,114,34,46), +(7,1,62,122,88,116,35,46), +(7,1,63,125,89,118,35,47), +(7,1,64,127,91,120,35,47), +(7,1,65,129,92,122,35,48), +(7,1,66,131,93,124,36,49), +(7,1,67,133,95,126,36,49), +(7,1,68,136,96,128,36,50), +(7,1,69,138,98,130,37,50), +(7,1,70,140,99,132,37,51), +(7,1,71,143,100,134,37,52), +(7,1,72,145,102,137,37,53), +(7,1,73,148,104,139,37,54), +(7,1,74,151,105,142,38,54), +(7,1,75,154,107,144,38,55), +(7,1,76,157,109,147,38,56), +(7,1,77,163,111,153,39,57), +(7,1,78,169,112,158,39,57), +(7,1,79,172,114,161,39,58), +(7,1,80,175,116,164,40,59), + +(7,4,1,16,26,20,24,20), +(7,4,2,17,27,21,24,20), +(7,4,3,18,29,21,24,21), +(7,4,4,18,30,22,24,21), +(7,4,5,19,32,23,25,21), +(7,4,6,20,33,24,25,22), +(7,4,7,21,35,24,25,22), +(7,4,8,22,36,25,25,23), +(7,4,9,22,38,26,25,23), +(7,4,10,23,39,26,25,23), +(7,4,11,24,41,27,25,24), +(7,4,12,25,42,28,26,24), +(7,4,13,26,44,29,26,25), +(7,4,14,27,46,30,26,25), +(7,4,15,28,47,30,26,25), +(7,4,16,28,49,31,26,26), +(7,4,17,29,50,32,27,26), +(7,4,18,30,52,33,27,27), +(7,4,19,31,54,34,27,27), +(7,4,20,32,56,35,27,28), +(7,4,21,33,57,35,27,28), +(7,4,22,34,59,36,28,29), +(7,4,23,35,61,37,28,29), +(7,4,24,36,62,38,28,30), +(7,4,25,37,64,39,28,30), +(7,4,26,38,66,40,29,31), +(7,4,27,39,68,41,29,31), +(7,4,28,40,70,42,29,32), +(7,4,29,41,72,43,29,32), +(7,4,30,42,73,43,29,33), +(7,4,31,43,75,44,30,33), +(7,4,32,44,77,45,30,34), +(7,4,33,45,79,46,30,34), +(7,4,34,46,81,47,31,35), +(7,4,35,47,83,48,31,35), +(7,4,36,48,85,49,31,36), +(7,4,37,49,87,50,31,36), +(7,4,38,50,89,51,32,37), +(7,4,39,51,91,52,32,38), +(7,4,40,53,93,53,32,38), +(7,4,41,54,95,54,33,39), +(7,4,42,55,97,55,33,39), +(7,4,43,56,99,56,33,40), +(7,4,44,57,101,57,33,40), +(7,4,45,58,103,59,34,41), +(7,4,46,59,105,60,34,42), +(7,4,47,61,107,61,34,42), +(7,4,48,62,110,62,35,43), +(7,4,49,63,112,63,35,44), +(7,4,50,64,114,64,35,44), +(7,4,51,65,116,65,36,45), +(7,4,52,67,118,66,36,45), +(7,4,53,68,121,67,36,46), +(7,4,54,69,123,69,37,47), +(7,4,55,70,125,70,37,47), +(7,4,56,72,127,71,37,48), +(7,4,57,73,130,72,38,49), +(7,4,58,74,132,73,38,49), +(7,4,59,75,134,74,39,50), +(7,4,60,77,137,76,39,51), +(7,4,61,78,139,77,39,51), +(7,4,62,79,141,78,40,52), +(7,4,63,81,144,79,40,53), +(7,4,64,82,146,80,41,54), +(7,4,65,83,149,82,41,54), +(7,4,66,85,151,83,41,55), +(7,4,67,86,154,84,42,56), +(7,4,68,87,156,85,42,57), +(7,4,69,89,158,87,43,57), +(7,4,70,90,161,88,43,58), +(7,4,71,92,164,89,44,59), +(7,4,72,94,167,91,45,59), +(7,4,73,95,170,93,45,60), +(7,4,74,97,173,94,46,61), +(7,4,75,99,176,96,46,62), +(7,4,76,100,179,97,46,63), +(7,4,77,102,182,102,47,64), +(7,4,78,104,186,105,47,65), +(7,4,79,106,189,106,48,66), +(7,4,80,108,192,108,48,67), + +(7,6,1,18,23,21,24,20), +(7,6,2,19,24,22,24,20), +(7,6,3,21,25,23,24,21), +(7,6,4,22,25,25,24,21), +(7,6,5,23,26,26,24,21), +(7,6,6,25,27,27,24,21), +(7,6,7,26,28,28,24,22), +(7,6,8,27,29,29,25,22), +(7,6,9,29,29,31,25,22), +(7,6,10,30,30,32,25,23), +(7,6,11,32,31,33,25,23), +(7,6,12,33,32,34,25,23), +(7,6,13,34,33,36,25,24), +(7,6,14,36,34,37,25,24), +(7,6,15,37,35,38,25,24), +(7,6,16,39,36,40,25,25), +(7,6,17,40,36,41,25,25), +(7,6,18,42,37,43,26,25), +(7,6,19,43,38,44,26,26), +(7,6,20,45,39,45,26,26), +(7,6,21,47,40,47,26,26), +(7,6,22,48,41,48,26,27), +(7,6,23,50,42,50,26,27), +(7,6,24,51,43,51,26,28), +(7,6,25,53,44,52,27,28), +(7,6,26,55,45,54,27,28), +(7,6,27,56,46,55,27,29), +(7,6,28,58,47,57,27,29), +(7,6,29,59,48,58,27,30), +(7,6,30,61,49,60,27,30), +(7,6,31,63,50,62,27,30), +(7,6,32,65,51,63,28,31), +(7,6,33,66,52,65,28,31), +(7,6,34,68,53,66,28,32), +(7,6,35,70,55,68,28,32), +(7,6,36,72,56,69,28,33), +(7,6,37,73,57,71,29,33), +(7,6,38,75,58,73,29,34), +(7,6,39,77,59,74,29,34), +(7,6,40,79,60,76,29,35), +(7,6,41,81,61,78,29,35), +(7,6,42,82,62,79,30,35), +(7,6,43,84,64,81,30,36), +(7,6,44,86,65,83,30,36), +(7,6,45,88,66,85,30,37), +(7,6,46,90,67,86,30,37), +(7,6,47,92,68,88,31,38), +(7,6,48,94,70,90,31,38), +(7,6,49,96,71,92,31,39), +(7,6,50,98,72,93,31,40), +(7,6,51,99,72,93,32,40), +(7,6,52,100,73,95,32,41), +(7,6,53,101,74,96,32,41), +(7,6,54,102,75,97,32,42), +(7,6,55,103,76,98,33,42), +(7,6,56,106,78,101,33,43), +(7,6,57,111,79,103,33,43), +(7,6,58,113,80,105,34,44), +(7,6,59,116,82,107,34,44), +(7,6,60,118,83,109,34,45), +(7,6,61,120,84,111,34,46), +(7,6,62,127,86,119,34,46), +(7,6,63,129,87,122,35,47), +(7,6,64,132,89,125,35,47), +(7,6,65,135,90,127,35,48), +(7,6,66,137,92,130,35,49), +(7,6,67,138,93,130,36,49), +(7,6,68,140,95,131,36,50), +(7,6,69,142,96,131,36,51), +(7,6,70,145,98,132,36,51), +(7,6,71,148,100,135,37,52), +(7,6,72,150,101,137,37,53), +(7,6,73,153,103,140,37,54), +(7,6,74,154,105,142,37,54), +(7,6,75,155,106,145,38,55), +(7,6,76,158,108,151,38,56), +(7,6,77,161,110,157,38,57), +(7,6,78,164,111,162,38,57), +(7,6,79,167,113,165,39,58), +(7,6,80,170,115,168,39,59), + +(7,8,1,15,23,19,27,22), +(7,8,2,15,23,19,28,23), +(7,8,3,15,23,20,30,25), +(7,8,4,15,23,20,31,26), +(7,8,5,15,24,20,32,27), +(7,8,6,15,24,20,34,29), +(7,8,7,16,24,21,35,30), +(7,8,8,16,24,21,37,31), +(7,8,9,16,24,21,38,33), +(7,8,10,16,24,22,40,34), +(7,8,11,16,25,22,41,36), +(7,8,12,16,25,22,42,37), +(7,8,13,16,25,23,44,38), +(7,8,14,16,25,23,45,40), +(7,8,15,17,25,23,47,41), +(7,8,16,17,25,24,49,43), +(7,8,17,17,26,24,50,44), +(7,8,18,17,26,24,52,46), +(7,8,19,17,26,25,53,47), +(7,8,20,17,26,25,55,49), +(7,8,21,17,26,26,57,51), +(7,8,22,18,27,26,58,52), +(7,8,23,18,27,26,60,54), +(7,8,24,18,27,27,61,55), +(7,8,25,18,27,27,63,57), +(7,8,26,18,28,27,65,59), +(7,8,27,18,28,28,67,60), +(7,8,28,18,28,28,68,62), +(7,8,29,19,28,29,70,64), +(7,8,30,19,29,29,72,65), +(7,8,31,19,29,30,74,67), +(7,8,32,19,29,30,75,69), +(7,8,33,19,29,30,77,70), +(7,8,34,20,30,31,79,72), +(7,8,35,20,30,31,81,74), +(7,8,36,20,30,32,83,76), +(7,8,37,20,30,32,85,78), +(7,8,38,20,31,33,86,79), +(7,8,39,21,31,33,88,81), +(7,8,40,21,31,34,90,83), +(7,8,41,21,32,34,92,85), +(7,8,42,21,32,35,94,87), +(7,8,43,21,32,35,96,89), +(7,8,44,22,32,36,98,91), +(7,8,45,22,33,36,100,92), +(7,8,46,22,33,37,102,94), +(7,8,47,22,33,37,104,96), +(7,8,48,22,34,38,106,98), +(7,8,49,23,34,38,108,100), +(7,8,50,23,34,39,110,102), +(7,8,51,23,35,39,112,104), +(7,8,52,23,35,40,114,106), +(7,8,53,24,35,40,117,108), +(7,8,54,24,36,41,119,110), +(7,8,55,24,36,41,121,112), +(7,8,56,24,37,42,123,114), +(7,8,57,25,37,42,125,117), +(7,8,58,25,37,43,127,119), +(7,8,59,25,38,43,130,121), +(7,8,60,25,38,44,132,123), +(7,8,61,26,38,45,134,125), +(7,8,62,26,39,45,136,127), +(7,8,63,26,39,46,139,129), +(7,8,64,26,40,46,141,132), +(7,8,65,27,40,47,143,134), +(7,8,66,27,40,48,146,136), +(7,8,67,27,41,48,148,138), +(7,8,68,27,41,49,150,140), +(7,8,69,28,42,49,153,143), +(7,8,70,28,42,50,155,145), +(7,8,71,28,42,51,168,148), +(7,8,72,28,43,52,168,151), +(7,8,73,28,43,53,171,154), +(7,8,74,29,44,53,174,156), +(7,8,75,29,44,54,177,159), +(7,8,76,29,44,55,180,162), +(7,8,77,30,45,56,183,165), +(7,8,78,30,45,56,186,168), +(7,8,79,30,46,57,190,171), +(7,8,80,31,46,58,193,174), + +(7,9,1,15,23,20,26,22), +(7,9,2,15,23,21,27,23), +(7,9,3,16,24,21,28,24), +(7,9,4,16,24,22,29,25), +(7,9,5,16,24,22,31,27), +(7,9,6,17,25,23,32,28), +(7,9,7,17,25,23,33,29), +(7,9,8,17,26,24,34,30), +(7,9,9,17,26,25,36,31), +(7,9,10,18,26,25,37,33), +(7,9,11,18,27,26,38,34), +(7,9,12,18,27,26,39,35), +(7,9,13,19,28,27,41,36), +(7,9,14,19,28,28,42,38), +(7,9,15,20,28,28,43,39), +(7,9,16,20,29,29,45,40), +(7,9,17,20,29,30,46,42), +(7,9,18,21,30,30,47,43), +(7,9,19,21,30,31,49,44), +(7,9,20,21,31,32,50,46), +(7,9,21,22,31,32,51,47), +(7,9,22,22,31,33,53,49), +(7,9,23,23,32,34,54,50), +(7,9,24,23,32,34,56,51), +(7,9,25,23,33,35,57,53), +(7,9,26,24,33,36,59,54), +(7,9,27,24,34,37,60,56), +(7,9,28,25,34,37,62,57), +(7,9,29,25,35,38,63,59), +(7,9,30,25,35,39,65,60), +(7,9,31,26,36,40,66,62), +(7,9,32,26,36,40,68,63), +(7,9,33,27,37,41,69,65), +(7,9,34,27,38,42,71,66), +(7,9,35,28,38,43,73,68), +(7,9,36,28,39,43,74,69), +(7,9,37,28,39,44,76,71), +(7,9,38,29,40,45,77,73), +(7,9,39,29,40,46,79,74), +(7,9,40,30,41,47,81,76), +(7,9,41,30,41,48,82,78), +(7,9,42,31,42,48,84,79), +(7,9,43,31,43,49,86,81), +(7,9,44,32,43,50,88,83), +(7,9,45,32,44,51,89,84), +(7,9,46,33,44,52,91,86), +(7,9,47,33,45,53,93,88), +(7,9,48,34,46,54,95,89), +(7,9,49,34,46,54,96,91), +(7,9,50,35,47,55,98,93), +(7,9,51,35,48,56,100,95), +(7,9,52,36,48,57,102,97), +(7,9,53,36,49,58,104,98), +(7,9,54,37,50,59,105,100), +(7,9,55,37,50,60,107,102), +(7,9,56,38,51,61,109,104), +(7,9,57,38,52,62,111,106), +(7,9,58,39,52,63,113,108), +(7,9,59,40,53,64,115,109), +(7,9,60,40,54,65,117,111), +(7,9,61,41,54,66,119,113), +(7,9,62,41,55,67,121,115), +(7,9,63,42,56,68,123,117), +(7,9,64,42,57,69,125,119), +(7,9,65,43,57,70,127,121), +(7,9,66,44,58,71,129,123), +(7,9,67,44,59,72,131,125), +(7,9,68,45,59,73,133,127), +(7,9,69,45,60,74,135,129), +(7,9,70,46,61,75,137,131), +(7,9,71,47,62,84,147,142), +(7,9,72,48,62,85,148,144), +(7,9,73,49,63,85,153,147), +(7,9,74,49,64,88,153,150), +(7,9,75,50,65,90,155,152), +(7,9,76,51,66,91,158,155), +(7,9,77,52,67,92,161,158), +(7,9,78,52,68,93,163,161), +(7,9,79,53,69,95,166,164), +(7,9,80,54,70,96,170,166), + +(8,1,1,24,22,23,16,21), +(8,1,2,25,23,24,16,21), +(8,1,3,27,24,25,16,22), +(8,1,4,28,24,26,16,22), +(8,1,5,29,25,28,16,22), +(8,1,6,31,26,29,16,22), +(8,1,7,32,27,30,17,23), +(8,1,8,33,28,31,17,23), +(8,1,9,35,28,33,17,23), +(8,1,10,36,29,34,17,24), +(8,1,11,37,30,35,17,24), +(8,1,12,39,31,36,17,24), +(8,1,13,40,32,38,17,25), +(8,1,14,42,33,39,17,25), +(8,1,15,43,34,40,18,25), +(8,1,16,45,35,42,18,26), +(8,1,17,46,35,43,18,26), +(8,1,18,48,36,44,18,26), +(8,1,19,49,37,46,18,27), +(8,1,20,51,38,47,18,27), +(8,1,21,52,39,49,18,27), +(8,1,22,54,40,50,18,28), +(8,1,23,55,41,51,19,28), +(8,1,24,57,42,53,19,29), +(8,1,25,59,43,54,19,29), +(8,1,26,60,44,56,19,29), +(8,1,27,62,45,57,19,30), +(8,1,28,63,46,59,19,30), +(8,1,29,65,47,60,20,31), +(8,1,30,67,48,62,20,31), +(8,1,31,69,49,63,20,31), +(8,1,32,70,50,65,20,32), +(8,1,33,72,51,67,20,32), +(8,1,34,74,53,68,20,33), +(8,1,35,75,54,70,21,33), +(8,1,36,77,55,71,21,34), +(8,1,37,79,56,73,21,34), +(8,1,38,81,57,75,21,35), +(8,1,39,83,58,76,21,35), +(8,1,40,84,59,78,22,35), +(8,1,41,86,60,80,22,36), +(8,1,42,88,62,81,22,36), +(8,1,43,90,63,83,22,37), +(8,1,44,92,64,85,22,37), +(8,1,45,94,65,86,23,38), +(8,1,46,96,66,88,23,38), +(8,1,47,98,67,90,23,39), +(8,1,48,100,69,92,23,39), +(8,1,49,102,70,93,24,40), +(8,1,50,103,71,95,24,40), +(8,1,51,105,72,97,24,41), +(8,1,52,107,74,99,24,42), +(8,1,53,109,75,101,25,42), +(8,1,54,112,76,103,25,43), +(8,1,55,114,78,104,25,43), +(8,1,56,116,79,106,25,44), +(8,1,57,118,80,108,25,44), +(8,1,58,120,81,110,26,45), +(8,1,59,122,83,112,26,45), +(8,1,60,124,84,114,26,46), +(8,1,61,126,85,116,27,47), +(8,1,62,128,87,118,27,47), +(8,1,63,130,88,120,27,48), +(8,1,64,133,90,122,27,48), +(8,1,65,135,91,124,28,49), +(8,1,66,137,92,126,28,50), +(8,1,67,139,94,128,28,50), +(8,1,68,141,95,130,28,51), +(8,1,69,144,97,132,29,51), +(8,1,70,146,98,134,29,52), +(8,1,71,149,99,136,29,53), +(8,1,72,151,101,139,29,54), +(8,1,73,154,103,141,29,55), +(8,1,74,157,104,144,30,55), +(8,1,75,166,106,151,30,56), +(8,1,76,172,108,157,30,57), +(8,1,77,175,110,161,31,58), +(8,1,78,179,111,163,31,58), +(8,1,79,182,113,164,31,59), +(8,1,80,185,115,169,32,60), + +(8,3,1,21,25,22,16,22), +(8,3,2,21,26,23,17,23), +(8,3,3,22,28,24,17,23), +(8,3,4,22,29,25,18,24), +(8,3,5,23,30,26,18,25), +(8,3,6,23,32,27,19,25), +(8,3,7,24,33,28,20,26), +(8,3,8,24,35,28,20,26), +(8,3,9,25,36,29,21,27), +(8,3,10,25,38,30,21,28), +(8,3,11,25,39,31,22,29), +(8,3,12,26,41,32,23,29), +(8,3,13,26,42,33,23,30), +(8,3,14,27,44,34,24,31), +(8,3,15,27,45,35,25,31), +(8,3,16,28,47,36,25,32), +(8,3,17,28,48,38,26,33), +(8,3,18,29,50,39,27,34), +(8,3,19,29,51,40,28,34), +(8,3,20,30,53,41,28,35), +(8,3,21,31,55,42,29,36), +(8,3,22,31,56,43,30,37), +(8,3,23,32,58,44,30,37), +(8,3,24,32,60,45,31,38), +(8,3,25,33,61,46,32,39), +(8,3,26,33,63,48,33,40), +(8,3,27,34,65,49,33,41), +(8,3,28,35,66,50,34,41), +(8,3,29,35,68,51,35,42), +(8,3,30,36,70,52,36,43), +(8,3,31,36,72,53,37,44), +(8,3,32,37,73,55,37,45), +(8,3,33,38,75,56,38,46), +(8,3,34,38,77,57,39,47), +(8,3,35,39,79,58,40,48), +(8,3,36,39,81,60,41,48), +(8,3,37,40,83,61,41,49), +(8,3,38,41,85,62,42,50), +(8,3,39,41,86,63,43,51), +(8,3,40,42,88,65,44,52), +(8,3,41,43,90,66,45,53), +(8,3,42,43,92,67,46,54), +(8,3,43,44,94,69,47,55), +(8,3,44,45,96,70,47,56), +(8,3,45,45,98,71,48,57), +(8,3,46,46,100,73,49,58), +(8,3,47,47,102,74,50,59), +(8,3,48,48,104,76,51,60), +(8,3,49,48,106,77,52,61), +(8,3,50,49,108,78,53,62), +(8,3,51,50,110,80,54,63), +(8,3,52,51,113,81,55,64), +(8,3,53,51,115,83,56,65), +(8,3,54,52,117,84,57,66), +(8,3,55,53,119,86,58,67), +(8,3,56,54,121,87,59,68), +(8,3,57,54,123,89,60,69), +(8,3,58,55,126,90,61,70), +(8,3,59,56,128,92,62,71), +(8,3,60,57,130,93,63,73), +(8,3,61,58,132,95,64,74), +(8,3,62,58,134,96,65,75), +(8,3,63,59,137,98,66,76), +(8,3,64,60,139,99,67,77), +(8,3,65,61,141,101,68,78), +(8,3,66,62,144,103,69,79), +(8,3,67,62,146,104,70,80), +(8,3,68,63,148,106,71,82), +(8,3,69,64,151,107,72,83), +(8,3,70,65,153,109,73,84), +(8,3,71,66,156,111,74,85), +(8,3,72,67,159,113,75,86), +(8,3,73,68,162,115,76,88), +(8,3,74,69,165,117,78,89), +(8,3,75,70,174,119,82,91), +(8,3,76,71,177,121,83,92), +(8,3,77,72,180,123,85,94), +(8,3,78,73,184,125,86,95), +(8,3,79,74,187,127,87,97), +(8,3,80,75,190,129,89,98), + +(8,4,1,22,25,22,16,21), +(8,4,2,23,26,23,16,21), +(8,4,3,24,28,23,16,22), +(8,4,4,24,29,24,16,22), +(8,4,5,25,31,25,17,22), +(8,4,6,26,32,25,17,23), +(8,4,7,27,34,26,17,23), +(8,4,8,27,35,27,17,24), +(8,4,9,28,37,28,17,24), +(8,4,10,29,38,28,18,24), +(8,4,11,30,40,29,18,25), +(8,4,12,31,41,30,18,25), +(8,4,13,32,43,31,18,26), +(8,4,14,32,45,32,18,26), +(8,4,15,33,46,32,19,26), +(8,4,16,34,48,33,19,27), +(8,4,17,35,50,34,19,27), +(8,4,18,36,51,35,19,28), +(8,4,19,37,53,36,19,28), +(8,4,20,38,55,36,20,29), +(8,4,21,39,56,37,20,29), +(8,4,22,40,58,38,20,30), +(8,4,23,41,60,39,20,30), +(8,4,24,42,62,40,20,31), +(8,4,25,43,63,41,21,31), +(8,4,26,44,65,42,21,32), +(8,4,27,45,67,43,21,32), +(8,4,28,46,69,44,21,33), +(8,4,29,47,71,44,22,33), +(8,4,30,48,72,45,22,34), +(8,4,31,49,74,46,22,34), +(8,4,32,50,76,47,22,35), +(8,4,33,51,78,48,23,35), +(8,4,34,52,80,49,23,36), +(8,4,35,53,82,50,23,36), +(8,4,36,54,84,51,24,37), +(8,4,37,55,86,52,24,37), +(8,4,38,56,88,53,24,38), +(8,4,39,57,90,54,24,38), +(8,4,40,58,92,55,25,39), +(8,4,41,59,94,56,25,40), +(8,4,42,60,96,57,25,40), +(8,4,43,62,98,58,26,41), +(8,4,44,63,100,59,26,41), +(8,4,45,64,102,60,26,42), +(8,4,46,65,104,61,27,43), +(8,4,47,66,107,63,27,43), +(8,4,48,67,109,64,27,44), +(8,4,49,69,111,65,27,44), +(8,4,50,70,113,66,28,45), +(8,4,51,71,115,67,28,46), +(8,4,52,72,117,68,28,46), +(8,4,53,74,120,69,29,47), +(8,4,54,75,122,70,29,48), +(8,4,55,76,124,72,29,48), +(8,4,56,77,126,73,30,49), +(8,4,57,79,129,74,30,50), +(8,4,58,80,131,75,30,50), +(8,4,59,81,133,76,31,51), +(8,4,60,82,136,77,31,52), +(8,4,61,84,138,79,32,52), +(8,4,62,85,140,80,32,53), +(8,4,63,86,143,81,32,54), +(8,4,64,88,145,82,33,55), +(8,4,65,89,148,84,33,55), +(8,4,66,90,150,85,33,56), +(8,4,67,92,153,86,34,57), +(8,4,68,93,155,87,34,58), +(8,4,69,95,157,89,35,58), +(8,4,70,96,160,90,35,59), +(8,4,71,98,163,94,35,60), +(8,4,72,100,166,96,36,60), +(8,4,73,101,169,96,36,61), +(8,4,74,103,172,97,37,62), +(8,4,75,105,175,98,37,63), +(8,4,76,106,178,99,37,64), +(8,4,77,108,181,105,38,65), +(8,4,78,110,185,107,38,66), +(8,4,79,112,188,109,39,67), +(8,4,80,114,191,110,39,68), + +(8,5,1,21,22,21,18,24), +(8,5,2,21,22,21,19,25), +(8,5,3,21,22,22,21,27), +(8,5,4,21,23,22,22,28), +(8,5,5,22,23,22,23,29), +(8,5,6,22,23,23,25,31), +(8,5,7,22,23,23,26,32), +(8,5,8,22,24,24,27,34), +(8,5,9,22,24,24,29,35), +(8,5,10,22,24,24,30,37), +(8,5,11,23,24,25,32,38), +(8,5,12,23,24,25,33,40), +(8,5,13,23,25,26,35,41), +(8,5,14,23,25,26,36,43), +(8,5,15,23,25,26,38,44), +(8,5,16,24,26,27,39,46), +(8,5,17,24,26,27,41,47), +(8,5,18,24,26,28,42,49), +(8,5,19,24,26,28,44,50), +(8,5,20,24,27,29,45,52), +(8,5,21,25,27,29,47,54), +(8,5,22,25,27,30,48,55), +(8,5,23,25,28,30,50,57), +(8,5,24,25,28,31,52,59), +(8,5,25,25,28,31,53,60), +(8,5,26,26,28,32,55,62), +(8,5,27,26,29,32,56,64), +(8,5,28,26,29,33,58,65), +(8,5,29,26,29,33,60,67), +(8,5,30,27,30,34,62,69), +(8,5,31,27,30,34,63,71), +(8,5,32,27,30,35,65,73), +(8,5,33,27,31,35,67,74), +(8,5,34,28,31,36,68,76), +(8,5,35,28,32,36,70,78), +(8,5,36,28,32,37,72,80), +(8,5,37,29,32,37,74,82), +(8,5,38,29,33,38,76,84), +(8,5,39,29,33,38,77,86), +(8,5,40,29,33,39,79,87), +(8,5,41,30,34,40,81,89), +(8,5,42,30,34,40,83,91), +(8,5,43,30,35,41,85,93), +(8,5,44,31,35,41,87,95), +(8,5,45,31,35,42,89,97), +(8,5,46,31,36,43,91,99), +(8,5,47,32,36,43,93,101), +(8,5,48,32,37,44,94,103), +(8,5,49,32,37,44,96,105), +(8,5,50,33,37,45,98,107), +(8,5,51,33,38,46,100,110), +(8,5,52,33,38,46,102,112), +(8,5,53,34,39,47,104,114), +(8,5,54,34,39,48,106,116), +(8,5,55,34,40,48,109,118), +(8,5,56,35,40,49,111,120), +(8,5,57,35,41,50,113,122), +(8,5,58,35,41,50,115,125), +(8,5,59,36,42,51,117,127), +(8,5,60,36,42,52,119,129), +(8,5,61,36,42,52,121,131), +(8,5,62,37,43,53,123,133), +(8,5,63,37,43,54,125,136), +(8,5,64,38,44,55,128,138), +(8,5,65,38,44,55,130,140), +(8,5,66,38,45,56,132,143), +(8,5,67,39,45,57,134,145), +(8,5,68,39,46,58,136,147), +(8,5,69,40,46,58,139,150), +(8,5,70,40,47,59,141,152), +(8,5,71,40,48,60,144,155), +(8,5,72,41,48,60,147,158), +(8,5,73,41,49,61,150,161), +(8,5,74,42,49,62,152,164), +(8,5,75,42,50,63,155,167), +(8,5,76,42,51,64,158,170), +(8,5,77,43,51,65,161,173), +(8,5,78,43,52,66,164,176), +(8,5,79,44,52,67,167,179), +(8,5,80,44,53,68,170,182), + +(8,6,1,24,22,23,16,21), +(8,6,2,25,23,24,16,21), +(8,6,3,27,24,25,16,22), +(8,6,4,28,24,26,16,22), +(8,6,5,29,25,28,16,22), +(8,6,6,31,26,29,16,22), +(8,6,7,32,27,30,17,23), +(8,6,8,33,28,31,17,23), +(8,6,9,35,28,33,17,23), +(8,6,10,36,29,34,17,24), +(8,6,11,37,30,35,17,24), +(8,6,12,39,31,36,17,24), +(8,6,13,40,32,38,17,25), +(8,6,14,42,33,39,17,25), +(8,6,15,43,34,40,18,25), +(8,6,16,45,35,42,18,26), +(8,6,17,46,35,43,18,26), +(8,6,18,48,36,44,18,26), +(8,6,19,49,37,46,18,27), +(8,6,20,51,38,47,18,27), +(8,6,21,52,39,49,18,27), +(8,6,22,54,40,50,18,28), +(8,6,23,55,41,51,19,28), +(8,6,24,57,42,53,19,29), +(8,6,25,59,43,54,19,29), +(8,6,26,60,44,56,19,29), +(8,6,27,62,45,57,19,30), +(8,6,28,63,46,59,19,30), +(8,6,29,65,47,60,20,31), +(8,6,30,67,48,62,20,31), +(8,6,31,69,49,63,20,31), +(8,6,32,70,50,65,20,32), +(8,6,33,72,51,67,20,32), +(8,6,34,74,53,68,20,33), +(8,6,35,75,54,70,21,33), +(8,6,36,77,55,71,21,34), +(8,6,37,79,56,73,21,34), +(8,6,38,81,57,75,21,35), +(8,6,39,83,58,76,21,35), +(8,6,40,84,59,78,22,35), +(8,6,41,86,60,80,22,36), +(8,6,42,88,62,81,22,36), +(8,6,43,90,63,83,22,37), +(8,6,44,92,64,85,22,37), +(8,6,45,94,65,86,23,38), +(8,6,46,96,66,88,23,38), +(8,6,47,98,67,90,23,39), +(8,6,48,100,69,92,23,39), +(8,6,49,102,70,93,24,40), +(8,6,50,103,71,95,24,40), +(8,6,51,105,72,96,24,41), +(8,6,52,106,74,97,24,42), +(8,6,53,107,73,98,25,42), +(8,6,54,108,74,99,25,43), +(8,6,55,109,75,100,25,43), +(8,6,56,112,77,103,25,44), +(8,6,57,114,78,105,25,44), +(8,6,58,118,79,107,26,45), +(8,6,59,119,81,109,26,45), +(8,6,60,121,82,111,26,46), +(8,6,61,123,83,113,26,47), +(8,6,62,126,85,115,26,47), +(8,6,63,128,86,118,27,48), +(8,6,64,131,88,120,27,48), +(8,6,65,138,89,122,27,49), +(8,6,66,140,91,125,27,50), +(8,6,67,143,92,127,28,50), +(8,6,68,145,94,129,28,51), +(8,6,69,148,95,132,28,52), +(8,6,70,151,97,134,28,52), +(8,6,71,154,99,137,29,53), +(8,6,72,156,100,139,29,54), +(8,6,73,159,102,142,29,55), +(8,6,74,162,104,144,29,55), +(8,6,75,165,105,147,30,56), +(8,6,76,168,107,150,30,57), +(8,6,77,169,109,153,30,58), +(8,6,78,170,110,155,30,58), +(8,6,79,178,112,158,31,59), +(8,6,80,181,114,161,31,60), + +(8,7,1,22,22,22,17,23), +(8,7,2,23,22,23,18,24), +(8,7,3,24,23,24,19,25), +(8,7,4,25,23,25,20,26), +(8,7,5,25,24,26,21,27), +(8,7,6,26,24,27,22,28), +(8,7,7,27,25,28,23,29), +(8,7,8,28,25,29,24,30), +(8,7,9,29,25,30,25,31), +(8,7,10,30,26,31,26,33), +(8,7,11,31,26,32,27,34), +(8,7,12,32,27,33,28,35), +(8,7,13,33,27,34,29,36), +(8,7,14,34,28,35,30,37), +(8,7,15,34,28,36,31,38), +(8,7,16,35,29,38,32,39), +(8,7,17,36,29,39,33,41), +(8,7,18,37,30,40,34,42), +(8,7,19,38,30,41,35,43), +(8,7,20,39,31,42,36,44), +(8,7,21,40,32,43,37,45), +(8,7,22,41,32,45,38,47), +(8,7,23,43,33,46,39,48), +(8,7,24,44,33,47,40,49), +(8,7,25,45,34,48,42,51), +(8,7,26,46,34,49,43,52), +(8,7,27,47,35,51,44,53), +(8,7,28,48,35,52,45,54), +(8,7,29,49,36,53,46,56), +(8,7,30,50,37,54,48,57), +(8,7,31,51,37,56,49,59), +(8,7,32,52,38,57,50,60), +(8,7,33,53,38,58,51,61), +(8,7,34,55,39,60,52,63), +(8,7,35,56,40,61,54,64), +(8,7,36,57,40,62,55,66), +(8,7,37,58,41,64,56,67), +(8,7,38,59,42,65,57,68), +(8,7,39,61,42,66,59,70), +(8,7,40,62,43,68,60,71), +(8,7,41,63,44,69,61,73), +(8,7,42,64,44,71,63,74), +(8,7,43,65,45,72,64,76), +(8,7,44,67,46,74,65,77), +(8,7,45,68,46,75,67,79), +(8,7,46,69,47,76,68,80), +(8,7,47,71,48,78,69,82), +(8,7,48,72,49,79,71,83), +(8,7,49,73,49,81,72,85), +(8,7,50,74,50,82,74,87), +(8,7,51,76,51,84,75,88), +(8,7,52,77,51,85,77,90), +(8,7,53,78,52,87,78,92), +(8,7,54,80,53,89,79,93), +(8,7,55,81,54,90,81,95), +(8,7,56,83,55,92,82,96), +(8,7,57,84,55,93,84,98), +(8,7,58,85,56,95,85,100), +(8,7,59,87,57,97,87,102), +(8,7,60,88,58,98,88,103), +(8,7,61,90,58,100,90,105), +(8,7,62,91,59,101,91,107), +(8,7,63,93,60,103,93,108), +(8,7,64,94,61,105,94,110), +(8,7,65,95,62,106,96,112), +(8,7,66,97,63,108,98,114), +(8,7,67,98,63,110,99,116), +(8,7,68,100,64,112,101,117), +(8,7,69,101,65,113,102,119), +(8,7,70,103,66,115,104,121), +(8,7,71,104,67,117,116,123), +(8,7,72,106,68,119,118,126), +(8,7,73,108,69,121,121,128), +(8,7,74,110,70,124,123,130), +(8,7,75,112,71,126,125,132), +(8,7,76,114,72,128,127,135), +(8,7,77,115,73,130,129,137), +(8,7,78,117,74,132,132,139), +(8,7,79,119,75,135,134,142), +(8,7,80,121,76,137,136,144), + +(8,8,1,21,22,21,19,23), +(8,8,2,21,22,21,20,24), +(8,8,3,21,22,22,22,26), +(8,8,4,21,22,22,23,27), +(8,8,5,21,23,22,25,28), +(8,8,6,21,23,22,26,30), +(8,8,7,21,23,23,27,31), +(8,8,8,22,23,23,29,32), +(8,8,9,22,23,23,30,34), +(8,8,10,22,23,24,32,35), +(8,8,11,22,24,24,33,37), +(8,8,12,22,24,24,35,38), +(8,8,13,22,24,25,36,39), +(8,8,14,22,24,25,38,41), +(8,8,15,22,24,25,39,42), +(8,8,16,22,24,26,41,44), +(8,8,17,23,25,26,42,45), +(8,8,18,23,25,26,44,47), +(8,8,19,23,25,27,46,48), +(8,8,20,23,25,27,47,50), +(8,8,21,23,25,27,49,51), +(8,8,22,23,26,28,51,53), +(8,8,23,23,26,28,52,55), +(8,8,24,24,26,29,54,56), +(8,8,25,24,26,29,56,58), +(8,8,26,24,27,29,57,60), +(8,8,27,24,27,30,59,61), +(8,8,28,24,27,30,61,63), +(8,8,29,24,27,31,63,65), +(8,8,30,24,28,31,64,66), +(8,8,31,25,28,31,66,68), +(8,8,32,25,28,32,68,70), +(8,8,33,25,28,32,70,71), +(8,8,34,25,29,33,71,73), +(8,8,35,25,29,33,73,75), +(8,8,36,26,29,34,75,77), +(8,8,37,26,29,34,77,79), +(8,8,38,26,30,35,79,80), +(8,8,39,26,30,35,81,82), +(8,8,40,26,30,35,83,84), +(8,8,41,27,31,36,85,86), +(8,8,42,27,31,36,87,88), +(8,8,43,27,31,37,89,90), +(8,8,44,27,32,37,91,91), +(8,8,45,27,32,38,93,93), +(8,8,46,28,32,38,95,95), +(8,8,47,28,32,39,97,97), +(8,8,48,28,33,39,99,99), +(8,8,49,28,33,40,101,101), +(8,8,50,29,33,40,103,103), +(8,8,51,29,34,41,105,105), +(8,8,52,29,34,42,107,107), +(8,8,53,29,35,42,109,109), +(8,8,54,30,35,43,111,111), +(8,8,55,30,35,43,113,113), +(8,8,56,30,36,44,115,115), +(8,8,57,30,36,44,118,118), +(8,8,58,31,36,45,120,120), +(8,8,59,31,37,45,122,122), +(8,8,60,31,37,46,124,124), +(8,8,61,31,37,47,126,126), +(8,8,62,32,38,47,129,128), +(8,8,63,32,38,48,131,130), +(8,8,64,32,39,48,133,133), +(8,8,65,33,39,49,135,135), +(8,8,66,33,39,50,138,137), +(8,8,67,33,40,50,140,139), +(8,8,68,33,40,51,142,141), +(8,8,69,34,41,51,145,144), +(8,8,70,34,41,52,147,146), +(8,8,71,34,41,53,150,149), +(8,8,72,34,42,54,153,152), +(8,8,73,34,42,55,156,155), +(8,8,74,35,43,55,159,157), +(8,8,75,35,43,56,162,160), +(8,8,76,35,43,57,168,163), +(8,8,77,36,44,58,168,166), +(8,8,78,36,44,58,171,169), +(8,8,79,36,45,59,177,172), +(8,8,80,37,45,60,177,175), + +(10,2,1,19,22,21,24,20), +(10,2,2,20,23,22,25,21), +(10,2,3,21,23,23,25,21), +(10,2,4,22,24,24,26,22), +(10,2,5,23,24,25,27,23), +(10,2,6,25,25,26,27,24), +(10,2,7,26,25,27,28,24), +(10,2,8,27,26,28,29,25), +(10,2,9,28,27,29,29,26), +(10,2,10,29,27,31,30,26), +(10,2,11,30,28,32,31,27), +(10,2,12,32,29,33,31,28), +(10,2,13,33,29,34,32,29), +(10,2,14,34,30,35,33,30), +(10,2,15,35,31,36,33,30), +(10,2,16,37,31,37,34,31), +(10,2,17,38,32,39,35,32), +(10,2,18,39,33,40,36,33), +(10,2,19,40,33,41,36,34), +(10,2,20,42,34,42,37,35), +(10,2,21,43,35,44,38,35), +(10,2,22,44,35,45,39,36), +(10,2,23,46,36,46,40,37), +(10,2,24,47,37,47,40,38), +(10,2,25,49,38,49,41,39), +(10,2,26,50,38,50,42,40), +(10,2,27,51,39,51,43,41), +(10,2,28,53,40,53,44,42), +(10,2,29,54,41,54,45,43), +(10,2,30,56,41,55,45,43), +(10,2,31,57,42,57,46,44), +(10,2,32,58,43,58,47,45), +(10,2,33,60,44,59,48,46), +(10,2,34,61,45,61,49,47), +(10,2,35,63,45,62,50,48), +(10,2,36,64,46,64,51,49), +(10,2,37,66,47,65,52,50), +(10,2,38,67,48,67,53,51), +(10,2,39,69,49,68,54,52), +(10,2,40,71,50,69,55,53), +(10,2,41,72,50,71,55,54), +(10,2,42,74,51,72,56,55), +(10,2,43,75,52,74,57,56), +(10,2,44,77,53,75,58,57), +(10,2,45,79,54,77,59,59), +(10,2,46,80,55,78,60,60), +(10,2,47,82,56,80,61,61), +(10,2,48,83,57,82,62,62), +(10,2,49,85,58,83,63,63), +(10,2,50,87,59,85,64,64), +(10,2,51,89,60,86,66,65), +(10,2,52,90,61,88,67,66), +(10,2,53,92,61,90,68,67), +(10,2,54,94,62,91,69,69), +(10,2,55,95,63,93,70,70), +(10,2,56,97,64,95,71,71), +(10,2,57,99,65,96,72,72), +(10,2,58,101,66,98,73,73), +(10,2,59,102,67,100,74,74), +(10,2,60,104,68,101,75,76), +(10,2,61,106,69,103,76,77), +(10,2,62,108,70,105,78,78), +(10,2,63,110,72,106,79,79), +(10,2,64,112,73,108,80,80), +(10,2,65,113,74,110,81,82), +(10,2,66,115,75,112,82,83), +(10,2,67,117,76,114,83,84), +(10,2,68,119,77,115,85,85), +(10,2,69,121,78,117,86,87), +(10,2,70,123,79,119,87,88), +(10,2,71,125,80,120,88,89), +(10,2,72,128,81,123,90,91), +(10,2,73,130,82,125,91,93), +(10,2,74,133,84,127,93,94), +(10,2,75,135,85,129,94,96), +(10,2,76,137,86,132,96,97), +(10,2,77,140,88,134,97,99), +(10,2,78,143,89,136,99,101), +(10,2,79,145,90,139,100,102), +(10,2,80,148,92,141,102,104), + +(10,3,1,17,25,20,24,20), +(10,3,2,17,26,21,25,21), +(10,3,3,18,28,22,25,21), +(10,3,4,18,29,23,26,22), +(10,3,5,19,30,24,26,23), +(10,3,6,19,32,25,27,23), +(10,3,7,20,33,26,27,24), +(10,3,8,20,35,27,28,25), +(10,3,9,21,36,27,29,25), +(10,3,10,21,38,28,29,26), +(10,3,11,22,39,29,30,27), +(10,3,12,22,41,30,31,27), +(10,3,13,23,42,31,31,28), +(10,3,14,23,44,32,32,29), +(10,3,15,24,45,34,32,29), +(10,3,16,24,47,35,33,30), +(10,3,17,25,48,36,34,31), +(10,3,18,25,50,37,34,32), +(10,3,19,26,51,38,35,32), +(10,3,20,26,53,39,36,33), +(10,3,21,27,55,40,37,34), +(10,3,22,27,56,41,37,35), +(10,3,23,28,58,42,38,36), +(10,3,24,28,60,43,39,36), +(10,3,25,29,61,44,39,37), +(10,3,26,30,63,46,40,38), +(10,3,27,30,65,47,41,39), +(10,3,28,31,66,48,42,40), +(10,3,29,31,68,49,42,40), +(10,3,30,32,70,50,43,41), +(10,3,31,33,72,52,44,42), +(10,3,32,33,73,53,45,43), +(10,3,33,34,75,54,46,44), +(10,3,34,34,77,55,46,45), +(10,3,35,35,79,57,47,46), +(10,3,36,36,81,58,48,47), +(10,3,37,36,83,59,49,47), +(10,3,38,37,85,60,50,48), +(10,3,39,38,86,62,51,49), +(10,3,40,38,88,63,51,50), +(10,3,41,39,90,64,52,51), +(10,3,42,40,92,66,53,52), +(10,3,43,40,94,67,54,53), +(10,3,44,41,96,68,55,54), +(10,3,45,42,98,70,56,55), +(10,3,46,42,100,71,57,56), +(10,3,47,43,102,72,58,57), +(10,3,48,44,104,74,59,58), +(10,3,49,45,106,75,60,59), +(10,3,50,45,108,77,61,60), +(10,3,51,46,110,78,61,61), +(10,3,52,47,113,79,62,62), +(10,3,53,47,115,81,63,63), +(10,3,54,48,117,82,64,64), +(10,3,55,49,119,84,65,65), +(10,3,56,50,121,85,66,66), +(10,3,57,50,123,87,67,67), +(10,3,58,51,126,88,68,68), +(10,3,59,52,128,90,69,70), +(10,3,60,53,130,91,70,71), +(10,3,61,54,132,93,71,72), +(10,3,62,54,134,94,72,73), +(10,3,63,55,137,96,73,74), +(10,3,64,56,139,97,75,75), +(10,3,65,57,141,99,76,76), +(10,3,66,58,144,101,77,77), +(10,3,67,58,146,102,78,78), +(10,3,68,59,148,104,79,80), +(10,3,69,60,151,105,80,81), +(10,3,70,61,153,107,81,82), +(10,3,71,62,156,108,82,83), +(10,3,72,63,159,110,83,84), +(10,3,73,64,162,112,84,86), +(10,3,74,65,165,114,86,87), +(10,3,75,66,168,116,87,89), +(10,3,76,67,171,118,89,90), +(10,3,77,68,174,120,90,92), +(10,3,78,69,177,122,91,93), +(10,3,79,70,180,124,92,95), +(10,3,80,71,183,126,94,96), + +(10,4,1,18,25,20,24,19), +(10,4,2,19,26,21,24,19), +(10,4,3,20,28,21,24,20), +(10,4,4,20,29,22,24,20), +(10,4,5,21,31,23,25,20), +(10,4,6,22,32,24,25,21), +(10,4,7,23,34,24,25,21), +(10,4,8,24,35,25,25,22), +(10,4,9,24,37,26,25,22), +(10,4,10,25,38,26,25,22), +(10,4,11,26,40,27,25,23), +(10,4,12,27,41,28,26,23), +(10,4,13,28,43,29,26,24), +(10,4,14,29,45,30,26,24), +(10,4,15,29,46,30,26,25), +(10,4,16,30,48,31,26,25), +(10,4,17,31,50,32,27,25), +(10,4,18,32,51,33,27,26), +(10,4,19,33,53,34,27,26), +(10,4,20,34,55,35,27,27), +(10,4,21,35,56,35,27,27), +(10,4,22,36,58,36,28,28), +(10,4,23,37,60,37,28,28), +(10,4,24,38,62,38,28,29), +(10,4,25,39,63,39,28,29), +(10,4,26,40,65,40,29,30), +(10,4,27,41,67,41,29,30), +(10,4,28,42,69,42,29,31), +(10,4,29,43,71,43,29,31), +(10,4,30,44,72,43,29,32), +(10,4,31,45,74,44,30,32), +(10,4,32,46,76,45,30,33), +(10,4,33,47,78,46,30,33), +(10,4,34,48,80,47,31,34), +(10,4,35,49,82,48,31,34), +(10,4,36,50,84,49,31,35), +(10,4,37,51,86,50,31,35), +(10,4,38,52,88,51,32,36), +(10,4,39,53,90,52,32,37), +(10,4,40,54,92,53,32,37), +(10,4,41,56,94,54,33,38), +(10,4,42,57,96,55,33,38), +(10,4,43,58,98,56,33,39), +(10,4,44,59,100,57,33,39), +(10,4,45,60,102,59,34,40), +(10,4,46,61,104,60,34,41), +(10,4,47,62,107,61,34,41), +(10,4,48,64,109,62,35,42), +(10,4,49,65,111,63,35,43), +(10,4,50,66,113,64,35,43), +(10,4,51,67,115,65,36,44), +(10,4,52,68,117,66,36,44), +(10,4,53,70,120,67,36,45), +(10,4,54,71,122,69,37,46), +(10,4,55,72,124,70,37,46), +(10,4,56,73,126,71,37,47), +(10,4,57,75,129,72,38,48), +(10,4,58,76,131,73,38,48), +(10,4,59,77,133,74,39,49), +(10,4,60,79,136,76,39,50), +(10,4,61,80,138,77,39,51), +(10,4,62,81,140,78,40,51), +(10,4,63,82,143,79,40,52), +(10,4,64,84,145,80,41,53), +(10,4,65,85,148,82,41,53), +(10,4,66,87,150,83,41,54), +(10,4,67,88,153,84,42,55), +(10,4,68,89,155,85,42,56), +(10,4,69,91,157,87,43,56), +(10,4,70,92,160,88,43,57), +(10,4,71,94,163,88,43,58), +(10,4,72,96,166,90,44,58), +(10,4,73,97,169,92,44,59), +(10,4,74,99,172,93,45,60), +(10,4,75,101,175,95,45,61), +(10,4,76,102,178,96,45,62), +(10,4,77,104,181,101,46,63), +(10,4,78,106,185,104,46,64), +(10,4,79,108,188,105,47,65), +(10,4,80,110,191,107,47,66), + +(10,5,1,17,22,19,26,22), +(10,5,2,17,22,19,27,23), +(10,5,3,17,22,20,29,25), +(10,5,4,17,23,20,30,26), +(10,5,5,18,23,20,31,27), +(10,5,6,18,23,21,33,29), +(10,5,7,18,23,21,34,30), +(10,5,8,18,24,22,35,32), +(10,5,9,18,24,22,37,33), +(10,5,10,19,24,22,38,35), +(10,5,11,19,24,23,39,36), +(10,5,12,19,24,23,41,38), +(10,5,13,19,25,24,42,39), +(10,5,14,19,25,24,44,41), +(10,5,15,19,25,25,45,42), +(10,5,16,20,26,25,47,44), +(10,5,17,20,26,25,48,45), +(10,5,18,20,26,26,50,47), +(10,5,19,20,26,26,51,49), +(10,5,20,21,27,27,53,50), +(10,5,21,21,27,27,54,52), +(10,5,22,21,27,28,56,53), +(10,5,23,21,28,28,58,55), +(10,5,24,21,28,29,59,57), +(10,5,25,22,28,29,61,58), +(10,5,26,22,28,30,62,60), +(10,5,27,22,29,30,64,62), +(10,5,28,22,29,31,66,64), +(10,5,29,23,29,31,67,65), +(10,5,30,23,30,32,69,67), +(10,5,31,23,30,32,71,69), +(10,5,32,23,30,33,72,71), +(10,5,33,24,31,33,74,72), +(10,5,34,24,31,34,76,74), +(10,5,35,24,32,34,78,76), +(10,5,36,24,32,35,80,78), +(10,5,37,25,32,35,81,80), +(10,5,38,25,33,36,83,82), +(10,5,39,25,33,37,85,84), +(10,5,40,26,33,37,87,86), +(10,5,41,26,34,38,89,88), +(10,5,42,26,34,38,91,89), +(10,5,43,27,35,39,92,91), +(10,5,44,27,35,39,94,93), +(10,5,45,27,35,40,96,95), +(10,5,46,27,36,41,98,97), +(10,5,47,28,36,41,100,99), +(10,5,48,28,37,42,102,101), +(10,5,49,28,37,43,104,103), +(10,5,50,29,37,43,106,106), +(10,5,51,29,38,44,108,108), +(10,5,52,29,38,44,110,110), +(10,5,53,30,39,45,112,112), +(10,5,54,30,39,46,114,114), +(10,5,55,30,40,46,116,116), +(10,5,56,31,40,47,118,118), +(10,5,57,31,41,48,120,120), +(10,5,58,31,41,48,123,123), +(10,5,59,32,42,49,125,125), +(10,5,60,32,42,50,127,127), +(10,5,61,33,42,51,129,129), +(10,5,62,33,43,51,131,131), +(10,5,63,33,43,52,133,134), +(10,5,64,34,44,53,135,136), +(10,5,65,34,44,53,138,138), +(10,5,66,34,45,54,140,141), +(10,5,67,35,45,55,142,143), +(10,5,68,35,46,56,144,145), +(10,5,69,36,46,56,147,148), +(10,5,70,36,47,57,149,150), +(10,5,71,36,48,57,152,153), +(10,5,72,37,48,57,155,156), +(10,5,73,37,49,58,158,159), +(10,5,74,38,49,59,160,163), +(10,5,75,38,50,60,163,165), +(10,5,76,38,51,61,166,170), +(10,5,77,39,51,62,168,175), +(10,5,78,39,52,63,172,174), +(10,5,79,40,52,64,175,177), +(10,5,80,40,53,65,178,180), + +(10,6,1,18,23,21,24,20), +(10,6,2,19,24,22,24,20), +(10,6,3,21,25,23,24,21), +(10,6,4,22,25,25,24,21), +(10,6,5,23,26,26,24,21), +(10,6,6,25,27,27,24,21), +(10,6,7,26,28,28,24,22), +(10,6,8,27,29,29,25,22), +(10,6,9,29,29,31,25,22), +(10,6,10,30,30,32,25,23), +(10,6,11,32,31,33,25,23), +(10,6,12,33,32,34,25,23), +(10,6,13,34,33,36,25,24), +(10,6,14,36,34,37,25,24), +(10,6,15,37,35,38,25,24), +(10,6,16,39,36,40,25,25), +(10,6,17,40,36,41,25,25), +(10,6,18,42,37,43,26,25), +(10,6,19,43,38,44,26,26), +(10,6,20,45,39,45,26,26), +(10,6,21,47,40,47,26,26), +(10,6,22,48,41,48,26,27), +(10,6,23,50,42,50,26,27), +(10,6,24,51,43,51,26,28), +(10,6,25,53,44,52,27,28), +(10,6,26,55,45,54,27,28), +(10,6,27,56,46,55,27,29), +(10,6,28,58,47,57,27,29), +(10,6,29,59,48,58,27,30), +(10,6,30,61,49,60,27,30), +(10,6,31,63,50,62,27,30), +(10,6,32,65,51,63,28,31), +(10,6,33,66,52,65,28,31), +(10,6,34,68,53,66,28,32), +(10,6,35,70,55,68,28,32), +(10,6,36,72,56,69,28,33), +(10,6,37,73,57,71,29,33), +(10,6,38,75,58,73,29,34), +(10,6,39,77,59,74,29,34), +(10,6,40,79,60,76,29,35), +(10,6,41,81,61,78,29,35), +(10,6,42,82,62,79,30,35), +(10,6,43,84,64,81,30,36), +(10,6,44,86,65,83,30,36), +(10,6,45,88,66,85,30,37), +(10,6,46,90,67,86,30,37), +(10,6,47,92,68,88,31,38), +(10,6,48,94,69,90,31,38), +(10,6,49,96,69,92,31,39), +(10,6,50,98,70,93,31,40), +(10,6,51,100,71,95,32,40), +(10,6,52,102,72,96,32,41), +(10,6,53,103,73,97,32,41), +(10,6,54,104,74,98,32,41), +(10,6,55,105,75,97,33,41), +(10,6,56,108,77,100,33,42), +(10,6,57,113,78,102,33,42), +(10,6,58,115,79,104,34,43), +(10,6,59,117,81,106,34,43), +(10,6,60,118,82,108,34,44), +(10,6,61,119,83,110,34,45), +(10,6,62,121,85,112,34,45), +(10,6,63,124,86,115,35,46), +(10,6,64,127,88,117,35,46), +(10,6,65,133,89,119,35,47), +(10,6,66,135,91,122,35,48), +(10,6,67,139,92,124,36,48), +(10,6,68,141,94,126,36,49), +(10,6,69,142,95,129,36,50), +(10,6,70,145,97,131,36,50), +(10,6,71,150,99,134,37,51), +(10,6,72,152,100,136,37,52), +(10,6,73,155,102,139,37,53), +(10,6,74,158,104,141,37,53), +(10,6,75,159,105,144,38,54), +(10,6,76,160,107,147,38,55), +(10,6,77,163,109,149,38,56), +(10,6,78,166,110,152,38,56), +(10,6,79,169,112,155,39,57), +(10,6,80,172,114,158,39,58), + +(10,8,1,17,22,19,27,21), +(10,8,2,17,22,19,28,22), +(10,8,3,17,22,20,30,24), +(10,8,4,17,22,20,31,25), +(10,8,5,17,23,20,32,26), +(10,8,6,17,23,20,34,28), +(10,8,7,18,23,21,35,29), +(10,8,8,18,23,21,37,30), +(10,8,9,18,23,21,38,32), +(10,8,10,18,23,22,40,33), +(10,8,11,18,24,22,41,35), +(10,8,12,18,24,22,42,36), +(10,8,13,18,24,23,44,37), +(10,8,14,18,24,23,45,39), +(10,8,15,18,24,23,47,40), +(10,8,16,19,24,24,49,42), +(10,8,17,19,25,24,50,43), +(10,8,18,19,25,24,52,45), +(10,8,19,19,25,25,53,46), +(10,8,20,19,25,25,55,48), +(10,8,21,19,25,26,57,50), +(10,8,22,19,26,26,58,51), +(10,8,23,20,26,26,60,53), +(10,8,24,20,26,27,61,54), +(10,8,25,20,26,27,63,56), +(10,8,26,20,27,27,65,58), +(10,8,27,20,27,28,67,59), +(10,8,28,20,27,28,68,61), +(10,8,29,21,27,29,70,63), +(10,8,30,21,28,29,72,64), +(10,8,31,21,28,30,74,66), +(10,8,32,21,28,30,75,68), +(10,8,33,21,28,30,77,70), +(10,8,34,21,29,31,79,71), +(10,8,35,22,29,31,81,73), +(10,8,36,22,29,32,83,75), +(10,8,37,22,29,32,85,77), +(10,8,38,22,30,33,86,78), +(10,8,39,22,30,33,88,80), +(10,8,40,23,30,34,90,82), +(10,8,41,23,31,34,92,84), +(10,8,42,23,31,35,94,86), +(10,8,43,23,31,35,96,88), +(10,8,44,23,32,36,98,90), +(10,8,45,24,32,36,100,92), +(10,8,46,24,32,37,102,93), +(10,8,47,24,32,37,104,95), +(10,8,48,24,33,38,106,97), +(10,8,49,25,33,38,108,99), +(10,8,50,25,33,39,110,101), +(10,8,51,25,34,39,112,103), +(10,8,52,25,34,40,114,105), +(10,8,53,25,35,40,117,107), +(10,8,54,26,35,41,119,109), +(10,8,55,26,35,41,121,111), +(10,8,56,26,36,42,123,113), +(10,8,57,26,36,42,125,116), +(10,8,58,27,36,43,127,118), +(10,8,59,27,37,43,130,120), +(10,8,60,27,37,44,132,122), +(10,8,61,27,37,45,134,124), +(10,8,62,28,38,45,136,126), +(10,8,63,28,38,46,139,128), +(10,8,64,28,39,46,141,131), +(10,8,65,29,39,47,143,133), +(10,8,66,29,39,48,146,135), +(10,8,67,29,40,48,148,137), +(10,8,68,29,40,49,150,139), +(10,8,69,30,41,49,153,142), +(10,8,70,30,41,50,155,144), +(10,8,71,30,41,50,158,147), +(10,8,72,30,42,51,161,150), +(10,8,73,30,42,52,164,153), +(10,8,74,31,43,52,167,155), +(10,8,75,31,43,53,170,158), +(10,8,76,31,43,54,173,161), +(10,8,77,32,44,55,176,164), +(10,8,78,32,44,55,179,167), +(10,8,79,32,45,56,182,170), +(10,8,80,33,45,57,185,173), + +(10,9,1,17,22,20,26,21), +(10,9,2,17,22,21,27,22), +(10,9,3,18,23,21,28,23), +(10,9,4,18,23,22,29,24), +(10,9,5,18,23,22,31,26), +(10,9,6,18,24,23,32,27), +(10,9,7,19,24,23,33,28), +(10,9,8,19,25,24,34,29), +(10,9,9,19,25,25,36,30), +(10,9,10,20,25,25,37,32), +(10,9,11,20,26,26,38,33), +(10,9,12,20,26,26,39,34), +(10,9,13,21,27,27,41,36), +(10,9,14,21,27,28,42,37), +(10,9,15,21,27,28,43,38), +(10,9,16,22,28,29,45,39), +(10,9,17,22,28,30,46,41), +(10,9,18,23,29,30,47,42), +(10,9,19,23,29,31,49,43), +(10,9,20,23,30,32,50,45), +(10,9,21,24,30,32,51,46), +(10,9,22,24,31,33,53,48), +(10,9,23,24,31,34,54,49), +(10,9,24,25,31,34,56,50), +(10,9,25,25,32,35,57,52), +(10,9,26,26,32,36,59,53), +(10,9,27,26,33,37,60,55), +(10,9,28,26,33,37,62,56), +(10,9,29,27,34,38,63,58), +(10,9,30,27,34,39,65,59), +(10,9,31,28,35,40,66,61), +(10,9,32,28,36,40,68,62), +(10,9,33,29,36,41,69,64), +(10,9,34,29,37,42,71,65), +(10,9,35,29,37,43,73,67), +(10,9,36,30,38,43,74,69), +(10,9,37,30,38,44,76,70), +(10,9,38,31,39,45,77,72), +(10,9,39,31,39,46,79,73), +(10,9,40,32,40,47,81,75), +(10,9,41,32,41,48,82,77), +(10,9,42,33,41,48,84,78), +(10,9,43,33,42,49,86,80), +(10,9,44,34,42,50,88,82), +(10,9,45,34,43,51,89,83), +(10,9,46,35,44,52,91,85), +(10,9,47,35,44,53,93,87), +(10,9,48,36,45,54,95,89), +(10,9,49,36,45,54,96,90), +(10,9,50,37,46,55,98,92), +(10,9,51,37,47,56,100,94), +(10,9,52,38,47,57,102,96), +(10,9,53,38,48,58,104,97), +(10,9,54,39,49,59,105,99), +(10,9,55,39,49,60,107,101), +(10,9,56,40,50,61,109,103), +(10,9,57,40,51,62,111,105), +(10,9,58,41,51,63,113,107), +(10,9,59,42,52,64,115,108), +(10,9,60,42,53,65,117,110), +(10,9,61,43,53,66,119,112), +(10,9,62,43,54,67,121,114), +(10,9,63,44,55,68,123,116), +(10,9,64,44,56,69,125,118), +(10,9,65,45,56,70,127,120), +(10,9,66,46,57,71,129,122), +(10,9,67,46,58,72,131,124), +(10,9,68,47,58,73,133,126), +(10,9,69,47,59,74,135,128), +(10,9,70,48,60,75,137,130), +(10,9,71,49,61,83,139,141), +(10,9,72,50,61,84,142,143), +(10,9,73,51,62,84,144,146), +(10,9,74,51,63,86,147,149), +(10,9,75,52,64,89,149,151), +(10,9,76,53,65,90,155,154), +(10,9,77,54,66,91,155,157), +(10,9,78,54,67,93,157,160), +(10,9,79,55,68,94,160,163), +(10,9,80,56,69,95,163,165), + +(11,1,1,24,17,21,21,22), +(11,1,2,25,18,22,21,22), +(11,1,3,27,19,23,21,23), +(11,1,4,28,19,25,21,23), +(11,1,5,29,20,26,21,23), +(11,1,6,31,21,27,21,23), +(11,1,7,32,22,28,21,24), +(11,1,8,33,23,29,22,24), +(11,1,9,35,24,31,22,24), +(11,1,10,36,24,32,22,25), +(11,1,11,37,25,33,22,25), +(11,1,12,39,26,34,22,25), +(11,1,13,40,27,36,22,26), +(11,1,14,42,28,37,22,26), +(11,1,15,43,29,38,22,26), +(11,1,16,45,30,40,22,27), +(11,1,17,46,31,41,23,27), +(11,1,18,48,32,43,23,27), +(11,1,19,49,33,44,23,28), +(11,1,20,51,34,45,23,28), +(11,1,21,52,34,47,23,28), +(11,1,22,54,35,48,23,29), +(11,1,23,55,36,50,23,29), +(11,1,24,57,37,51,24,30), +(11,1,25,59,38,52,24,30), +(11,1,26,60,39,54,24,30), +(11,1,27,62,40,55,24,31), +(11,1,28,63,41,57,24,31), +(11,1,29,65,43,58,24,32), +(11,1,30,67,44,60,24,32), +(11,1,31,69,45,62,25,32), +(11,1,32,70,46,63,25,33), +(11,1,33,72,47,65,25,33), +(11,1,34,74,48,66,25,34), +(11,1,35,75,49,68,25,34), +(11,1,36,77,50,69,26,35), +(11,1,37,79,51,71,26,35), +(11,1,38,81,52,73,26,35), +(11,1,39,83,53,74,26,36), +(11,1,40,84,55,76,26,36), +(11,1,41,86,56,78,27,37), +(11,1,42,88,57,79,27,37), +(11,1,43,90,58,81,27,38), +(11,1,44,92,59,83,27,38), +(11,1,45,94,60,85,27,39), +(11,1,46,96,62,86,28,39), +(11,1,47,98,63,88,28,40), +(11,1,48,100,64,90,28,40), +(11,1,49,102,65,92,28,41), +(11,1,50,103,66,93,29,41), +(11,1,51,105,68,95,29,42), +(11,1,52,107,69,97,29,42), +(11,1,53,109,70,99,29,43), +(11,1,54,112,71,101,30,44), +(11,1,55,114,73,103,30,44), +(11,1,56,116,74,104,30,45), +(11,1,57,118,75,106,30,45), +(11,1,58,120,77,108,31,46), +(11,1,59,122,78,110,31,46), +(11,1,60,124,79,112,31,47), +(11,1,61,126,81,114,31,48), +(11,1,62,128,82,116,32,48), +(11,1,63,130,83,118,32,49), +(11,1,64,133,85,120,32,49), +(11,1,65,135,86,122,33,50), +(11,1,66,137,87,124,33,51), +(11,1,67,139,89,126,33,51), +(11,1,68,141,90,128,33,52), +(11,1,69,144,92,130,34,52), +(11,1,70,146,93,132,34,53), +(11,1,71,149,94,134,34,54), +(11,1,72,151,96,137,34,55), +(11,1,73,154,98,139,34,56), +(11,1,74,157,99,142,35,56), +(11,1,75,166,101,149,35,57), +(11,1,76,172,103,155,35,58), +(11,1,77,175,105,159,36,59), +(11,1,78,179,106,161,36,59), +(11,1,79,182,108,164,36,60), +(11,1,80,185,110,167,37,61), + +(11,2,1,23,17,21,21,23), +(11,2,2,24,18,22,22,24), +(11,2,3,25,18,23,22,24), +(11,2,4,26,19,24,23,25), +(11,2,5,27,19,25,24,26), +(11,2,6,29,20,26,24,26), +(11,2,7,30,21,27,25,27), +(11,2,8,31,21,28,26,28), +(11,2,9,32,22,29,26,29), +(11,2,10,33,22,31,27,29), +(11,2,11,34,23,32,28,30), +(11,2,12,36,24,33,28,31), +(11,2,13,37,24,34,29,32), +(11,2,14,38,25,35,30,32), +(11,2,15,39,26,36,31,33), +(11,2,16,40,26,37,31,34), +(11,2,17,42,27,39,32,35), +(11,2,18,43,28,40,33,36), +(11,2,19,44,28,41,34,37), +(11,2,20,46,29,42,34,37), +(11,2,21,47,30,44,35,38), +(11,2,22,48,31,45,36,39), +(11,2,23,50,31,46,37,40), +(11,2,24,51,32,47,38,41), +(11,2,25,52,33,49,38,42), +(11,2,26,54,34,50,39,43), +(11,2,27,55,34,51,40,44), +(11,2,28,56,35,53,41,44), +(11,2,29,58,36,54,42,45), +(11,2,30,59,37,55,43,46), +(11,2,31,61,37,57,43,47), +(11,2,32,62,38,58,44,48), +(11,2,33,64,39,59,45,49), +(11,2,34,65,40,61,46,50), +(11,2,35,67,41,62,47,51), +(11,2,36,68,42,64,48,52), +(11,2,37,70,42,65,49,53), +(11,2,38,71,43,67,50,54), +(11,2,39,73,44,68,51,55), +(11,2,40,74,45,69,52,56), +(11,2,41,76,46,71,53,57), +(11,2,42,78,47,72,54,58), +(11,2,43,79,47,74,55,59), +(11,2,44,81,48,75,56,60), +(11,2,45,82,49,77,57,61), +(11,2,46,84,50,78,58,62), +(11,2,47,86,51,80,59,64), +(11,2,48,87,52,82,60,65), +(11,2,49,89,53,83,61,66), +(11,2,50,91,54,85,62,67), +(11,2,51,92,55,86,63,68), +(11,2,52,94,56,88,64,69), +(11,2,53,96,57,90,65,70), +(11,2,54,97,58,91,66,71), +(11,2,55,99,59,93,67,73), +(11,2,56,101,60,95,68,74), +(11,2,57,103,61,96,69,75), +(11,2,58,105,62,98,70,76), +(11,2,59,106,63,100,71,77), +(11,2,60,108,64,101,72,78), +(11,2,61,110,65,103,74,80), +(11,2,62,112,66,105,75,81), +(11,2,63,114,67,106,76,82), +(11,2,64,116,68,108,77,83), +(11,2,65,117,69,110,78,85), +(11,2,66,119,70,112,79,86), +(11,2,67,121,71,114,80,87), +(11,2,68,123,72,115,82,88), +(11,2,69,125,73,117,83,90), +(11,2,70,127,74,119,84,91), +(11,2,71,130,75,121,87,92), +(11,2,72,132,76,124,90,94), +(11,2,73,134,77,126,93,96), +(11,2,74,137,79,128,97,97), +(11,2,75,139,80,130,101,99), +(11,2,76,142,81,133,106,100), +(11,2,77,144,83,135,108,102), +(11,2,78,147,84,137,110,104), +(11,2,79,149,85,140,111,105), +(11,2,80,152,87,142,113,107), + +(11,3,1,21,20,20,21,23), +(11,3,2,21,21,21,22,24), +(11,3,3,22,23,22,22,24), +(11,3,4,22,24,23,23,25), +(11,3,5,23,25,24,23,25), +(11,3,6,23,27,25,24,26), +(11,3,7,24,28,26,24,27), +(11,3,8,24,30,27,25,27), +(11,3,9,25,31,27,26,28), +(11,3,10,25,33,28,26,29), +(11,3,11,25,34,29,27,29), +(11,3,12,26,36,30,28,30), +(11,3,13,26,37,31,28,31), +(11,3,14,27,39,32,29,32), +(11,3,15,27,40,34,30,32), +(11,3,16,28,42,35,30,33), +(11,3,17,28,43,36,31,34), +(11,3,18,29,45,37,32,35), +(11,3,19,29,47,38,32,35), +(11,3,20,30,48,39,33,36), +(11,3,21,31,50,40,34,37), +(11,3,22,31,51,41,34,38), +(11,3,23,32,53,42,35,38), +(11,3,24,32,55,43,36,39), +(11,3,25,33,57,44,37,40), +(11,3,26,33,58,46,37,41), +(11,3,27,34,60,47,38,42), +(11,3,28,35,62,48,39,42), +(11,3,29,35,63,49,40,43), +(11,3,30,36,65,50,40,44), +(11,3,31,36,67,52,41,45), +(11,3,32,37,69,53,42,46), +(11,3,33,38,71,54,43,47), +(11,3,34,38,72,55,44,48), +(11,3,35,39,74,57,44,48), +(11,3,36,39,76,58,45,49), +(11,3,37,40,78,59,46,50), +(11,3,38,41,80,60,47,51), +(11,3,39,41,82,62,48,52), +(11,3,40,42,84,63,49,53), +(11,3,41,43,86,64,50,54), +(11,3,42,43,88,66,50,55), +(11,3,43,44,90,67,51,56), +(11,3,44,45,91,68,52,57), +(11,3,45,45,93,70,53,58), +(11,3,46,46,95,71,54,59), +(11,3,47,47,98,72,55,60), +(11,3,48,48,100,74,56,61), +(11,3,49,48,102,75,57,62), +(11,3,50,49,104,77,58,63), +(11,3,51,50,106,78,59,64), +(11,3,52,51,108,79,60,65), +(11,3,53,51,110,81,61,66), +(11,3,54,52,112,82,61,67), +(11,3,55,53,114,84,62,68), +(11,3,56,54,116,85,63,69), +(11,3,57,54,118,87,64,70), +(11,3,58,55,121,88,65,71), +(11,3,59,56,123,90,66,72), +(11,3,60,57,125,91,67,74), +(11,3,61,58,127,93,68,75), +(11,3,62,58,130,94,69,76), +(11,3,63,59,132,96,71,77), +(11,3,64,60,134,97,72,78), +(11,3,65,61,136,99,73,79), +(11,3,66,62,139,101,74,80), +(11,3,67,62,141,102,75,81), +(11,3,68,63,143,104,76,83), +(11,3,69,64,146,105,77,84), +(11,3,70,65,148,107,78,85), +(11,3,71,66,151,109,79,86), +(11,3,72,67,154,111,80,87), +(11,3,73,68,157,113,81,89), +(11,3,74,69,160,115,83,90), +(11,3,75,70,163,117,84,92), +(11,3,76,71,166,119,85,93), +(11,3,77,72,169,121,87,95), +(11,3,78,73,172,123,88,96), +(11,3,79,74,175,125,89,98), +(11,3,80,75,178,127,91,99), + +(11,5,1,21,17,19,23,25), +(11,5,2,21,17,19,24,26), +(11,5,3,21,17,20,26,28), +(11,5,4,21,18,20,27,29), +(11,5,5,22,18,20,28,30), +(11,5,6,22,18,21,30,32), +(11,5,7,22,18,21,31,33), +(11,5,8,22,19,22,32,35), +(11,5,9,22,19,22,34,36), +(11,5,10,22,19,22,35,38), +(11,5,11,23,19,23,37,39), +(11,5,12,23,20,23,38,41), +(11,5,13,23,20,24,39,42), +(11,5,14,23,20,24,41,44), +(11,5,15,23,20,25,42,45), +(11,5,16,24,21,25,44,47), +(11,5,17,24,21,25,45,48), +(11,5,18,24,21,26,47,50), +(11,5,19,24,22,26,48,51), +(11,5,20,24,22,27,50,53), +(11,5,21,25,22,27,51,55), +(11,5,22,25,22,28,53,56), +(11,5,23,25,23,28,55,58), +(11,5,24,25,23,29,56,60), +(11,5,25,25,23,29,58,61), +(11,5,26,26,24,30,60,63), +(11,5,27,26,24,30,61,65), +(11,5,28,26,24,31,63,66), +(11,5,29,26,25,31,65,68), +(11,5,30,27,25,32,66,70), +(11,5,31,27,25,32,68,72), +(11,5,32,27,26,33,70,73), +(11,5,33,27,26,33,71,75), +(11,5,34,28,26,34,73,77), +(11,5,35,28,27,34,75,79), +(11,5,36,28,27,35,77,81), +(11,5,37,29,28,35,79,83), +(11,5,38,29,28,36,80,85), +(11,5,39,29,28,37,82,86), +(11,5,40,29,29,37,84,88), +(11,5,41,30,29,38,86,90), +(11,5,42,30,29,38,88,92), +(11,5,43,30,30,39,90,94), +(11,5,44,31,30,39,91,96), +(11,5,45,31,31,40,93,98), +(11,5,46,31,31,41,95,100), +(11,5,47,32,31,41,97,102), +(11,5,48,32,32,42,99,104), +(11,5,49,32,32,43,101,106), +(11,5,50,33,33,43,103,108), +(11,5,51,33,33,44,105,110), +(11,5,52,33,34,44,107,113), +(11,5,53,34,34,45,109,115), +(11,5,54,34,34,46,111,117), +(11,5,55,34,35,46,113,119), +(11,5,56,35,35,47,115,121), +(11,5,57,35,36,48,118,123), +(11,5,58,35,36,48,120,126), +(11,5,59,36,37,49,122,128), +(11,5,60,36,37,50,124,130), +(11,5,61,36,38,51,126,132), +(11,5,62,37,38,51,128,134), +(11,5,63,37,39,52,130,137), +(11,5,64,38,39,53,133,139), +(11,5,65,38,40,53,135,141), +(11,5,66,38,40,54,137,144), +(11,5,67,39,40,55,139,146), +(11,5,68,39,41,56,141,148), +(11,5,69,40,41,56,144,151), +(11,5,70,40,42,57,146,153), +(11,5,71,40,43,58,149,156), +(11,5,72,41,43,58,155,159), +(11,5,73,41,44,59,157,160), +(11,5,74,42,44,61,160,163), +(11,5,75,42,45,62,164,166), +(11,5,76,42,46,62,167,169), +(11,5,77,43,46,63,168,172), +(11,5,78,43,47,64,169,177), +(11,5,79,44,47,65,172,180), +(11,5,80,44,48,66,175,183), + +(11,6,1,24,17,21,21,22), +(11,6,2,25,18,22,21,22), +(11,6,3,27,19,23,21,23), +(11,6,4,28,19,25,21,23), +(11,6,5,29,20,26,21,23), +(11,6,6,31,21,27,21,23), +(11,6,7,32,22,28,21,24), +(11,6,8,33,23,29,22,24), +(11,6,9,35,24,31,22,24), +(11,6,10,36,24,32,22,25), +(11,6,11,37,25,33,22,25), +(11,6,12,39,26,34,22,25), +(11,6,13,40,27,36,22,26), +(11,6,14,42,28,37,22,26), +(11,6,15,43,29,38,22,26), +(11,6,16,45,30,40,22,27), +(11,6,17,46,31,41,23,27), +(11,6,18,48,32,43,23,27), +(11,6,19,49,33,44,23,28), +(11,6,20,51,34,45,23,28), +(11,6,21,52,34,47,23,28), +(11,6,22,54,35,48,23,29), +(11,6,23,55,36,50,23,29), +(11,6,24,57,37,51,24,30), +(11,6,25,59,38,52,24,30), +(11,6,26,60,39,54,24,30), +(11,6,27,62,40,55,24,31), +(11,6,28,63,41,57,24,31), +(11,6,29,65,43,58,24,32), +(11,6,30,67,44,60,24,32), +(11,6,31,69,45,62,25,32), +(11,6,32,70,46,63,25,33), +(11,6,33,72,47,65,25,33), +(11,6,34,74,48,66,25,34), +(11,6,35,75,49,68,25,34), +(11,6,36,77,50,69,26,35), +(11,6,37,79,51,71,26,35), +(11,6,38,81,52,73,26,35), +(11,6,39,83,53,74,26,36), +(11,6,40,84,55,76,26,36), +(11,6,41,86,56,78,27,37), +(11,6,42,88,57,79,27,37), +(11,6,43,90,58,81,27,38), +(11,6,44,92,59,83,27,38), +(11,6,45,94,60,85,27,39), +(11,6,46,96,62,86,28,39), +(11,6,47,98,63,88,28,40), +(11,6,48,100,64,90,28,40), +(11,6,49,102,65,92,28,41), +(11,6,50,103,65,93,29,41), +(11,6,51,105,66,94,29,42), +(11,6,52,106,67,95,29,42), +(11,6,53,107,68,96,29,43), +(11,6,54,108,69,97,30,44), +(11,6,55,109,70,98,30,44), +(11,6,56,112,72,101,30,45), +(11,6,57,114,73,103,30,45), +(11,6,58,117,74,105,31,46), +(11,6,59,119,76,107,31,46), +(11,6,60,121,77,109,31,47), +(11,6,61,123,78,111,31,48), +(11,6,62,126,80,113,31,48), +(11,6,63,128,81,116,32,49), +(11,6,64,131,83,118,32,49), +(11,6,65,136,84,120,32,50), +(11,6,66,140,86,123,32,51), +(11,6,67,141,87,125,33,51), +(11,6,68,141,89,127,33,52), +(11,6,69,144,90,130,33,53), +(11,6,70,147,92,132,33,53), +(11,6,71,150,94,135,34,54), +(11,6,72,152,95,137,34,55), +(11,6,73,155,97,140,34,56), +(11,6,74,162,99,142,34,56), +(11,6,75,165,100,145,35,57), +(11,6,76,167,102,146,35,58), +(11,6,77,169,104,150,35,59), +(11,6,78,170,105,152,35,59), +(11,6,79,173,107,156,36,60), +(11,6,80,176,109,159,36,61), + +(11,7,1,22,17,20,22,24), +(11,7,2,23,17,21,23,25), +(11,7,3,24,18,22,24,26), +(11,7,4,25,18,23,25,27), +(11,7,5,25,19,24,26,28), +(11,7,6,26,19,25,27,29), +(11,7,7,27,20,26,28,30), +(11,7,8,28,20,27,28,31), +(11,7,9,29,21,28,29,32), +(11,7,10,30,21,29,30,33), +(11,7,11,31,22,30,31,35), +(11,7,12,32,22,31,32,36), +(11,7,13,33,23,32,33,37), +(11,7,14,34,23,33,34,38), +(11,7,15,34,24,35,35,39), +(11,7,16,35,24,36,36,40), +(11,7,17,36,25,37,38,42), +(11,7,18,37,25,38,39,43), +(11,7,19,38,26,39,40,44), +(11,7,20,39,26,40,41,45), +(11,7,21,40,27,41,42,46), +(11,7,22,41,27,43,43,48), +(11,7,23,43,28,44,44,49), +(11,7,24,44,28,45,45,50), +(11,7,25,45,29,46,46,51), +(11,7,26,46,30,47,48,53), +(11,7,27,47,30,49,49,54), +(11,7,28,48,31,50,50,55), +(11,7,29,49,31,51,51,57), +(11,7,30,50,32,53,52,58), +(11,7,31,51,33,54,53,59), +(11,7,32,52,33,55,55,61), +(11,7,33,53,34,56,56,62), +(11,7,34,55,34,58,57,64), +(11,7,35,56,35,59,58,65), +(11,7,36,57,36,60,60,66), +(11,7,37,58,36,62,61,68), +(11,7,38,59,37,63,62,69), +(11,7,39,61,38,65,63,71), +(11,7,40,62,38,66,65,72), +(11,7,41,63,39,67,66,74), +(11,7,42,64,40,69,67,75), +(11,7,43,65,40,70,69,77), +(11,7,44,67,41,72,70,78), +(11,7,45,68,42,73,71,80), +(11,7,46,69,42,75,73,81), +(11,7,47,71,43,76,74,83), +(11,7,48,72,44,78,76,84), +(11,7,49,73,45,79,77,86), +(11,7,50,74,45,81,78,88), +(11,7,51,76,46,82,80,89), +(11,7,52,77,47,84,81,91), +(11,7,53,78,47,85,83,92), +(11,7,54,80,48,87,84,94), +(11,7,55,81,49,88,86,96), +(11,7,56,83,50,90,87,97), +(11,7,57,84,50,91,89,99), +(11,7,58,85,51,93,90,101), +(11,7,59,87,52,95,92,102), +(11,7,60,88,53,96,93,104), +(11,7,61,90,54,98,95,106), +(11,7,62,91,54,99,96,108), +(11,7,63,93,55,101,98,109), +(11,7,64,94,56,103,99,111), +(11,7,65,95,57,104,101,113), +(11,7,66,97,58,106,103,115), +(11,7,67,98,58,108,104,117), +(11,7,68,100,59,110,106,118), +(11,7,69,101,60,111,107,120), +(11,7,70,103,61,113,109,122), +(11,7,71,104,62,115,122,124), +(11,7,72,106,63,117,124,127), +(11,7,73,108,64,119,126,129), +(11,7,74,110,65,122,128,131), +(11,7,75,112,66,124,130,133), +(11,7,76,114,67,126,133,136), +(11,7,77,115,68,128,135,138), +(11,7,78,117,69,130,137,140), +(11,7,79,119,70,133,139,143), +(11,7,80,121,71,135,141,145), + +(11,8,1,21,17,19,24,24), +(11,8,2,21,17,19,25,25), +(11,8,3,21,17,20,27,27), +(11,8,4,21,17,20,28,28), +(11,8,5,21,18,20,29,29), +(11,8,6,21,18,20,31,31), +(11,8,7,21,18,21,32,32), +(11,8,8,22,18,21,34,33), +(11,8,9,22,18,21,35,35), +(11,8,10,22,19,22,37,36), +(11,8,11,22,19,22,38,37), +(11,8,12,22,19,22,40,39), +(11,8,13,22,19,23,41,40), +(11,8,14,22,19,23,43,42), +(11,8,15,22,19,23,44,43), +(11,8,16,22,20,24,46,45), +(11,8,17,23,20,24,47,46), +(11,8,18,23,20,24,49,48), +(11,8,19,23,20,25,50,49), +(11,8,20,23,21,25,52,51), +(11,8,21,23,21,26,54,52), +(11,8,22,23,21,26,55,54), +(11,8,23,23,21,26,57,56), +(11,8,24,24,21,27,59,57), +(11,8,25,24,22,27,60,59), +(11,8,26,24,22,27,62,60), +(11,8,27,24,22,28,64,62), +(11,8,28,24,22,28,65,64), +(11,8,29,24,23,29,67,65), +(11,8,30,24,23,29,69,67), +(11,8,31,25,23,30,71,69), +(11,8,32,25,23,30,73,71), +(11,8,33,25,24,30,74,72), +(11,8,34,25,24,31,76,74), +(11,8,35,25,24,31,78,76), +(11,8,36,26,24,32,80,78), +(11,8,37,26,25,32,82,79), +(11,8,38,26,25,33,84,81), +(11,8,39,26,25,33,86,83), +(11,8,40,26,26,34,87,85), +(11,8,41,27,26,34,89,87), +(11,8,42,27,26,35,91,89), +(11,8,43,27,27,35,93,91), +(11,8,44,27,27,36,95,92), +(11,8,45,27,27,36,97,94), +(11,8,46,28,27,37,99,96), +(11,8,47,28,28,37,101,98), +(11,8,48,28,28,38,103,100), +(11,8,49,28,28,38,105,102), +(11,8,50,29,29,39,107,104), +(11,8,51,29,29,39,110,106), +(11,8,52,29,29,40,112,108), +(11,8,53,29,30,40,114,110), +(11,8,54,30,30,41,116,112), +(11,8,55,30,30,41,118,114), +(11,8,56,30,31,42,120,116), +(11,8,57,30,31,42,122,118), +(11,8,58,31,31,43,125,121), +(11,8,59,31,32,43,127,123), +(11,8,60,31,32,44,129,125), +(11,8,61,31,33,45,131,127), +(11,8,62,32,33,45,133,129), +(11,8,63,32,33,46,136,131), +(11,8,64,32,34,46,138,134), +(11,8,65,33,34,47,140,136), +(11,8,66,33,34,48,143,138), +(11,8,67,33,35,48,145,140), +(11,8,68,33,35,49,147,142), +(11,8,69,34,36,49,150,145), +(11,8,70,34,36,50,152,147), +(11,8,71,34,36,51,155,150), +(11,8,72,34,37,52,161,153), +(11,8,73,34,37,53,161,156), +(11,8,74,35,38,53,164,158), +(11,8,75,35,38,54,167,161), +(11,8,76,35,38,55,170,164), +(11,8,77,36,39,56,173,167), +(11,8,78,36,39,56,176,170), +(11,8,79,36,40,57,179,173), +(11,8,80,37,40,58,182,176); From 28d2d45a4612679eca91d0ac66f258941e528198 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Thu, 18 Dec 2008 14:30:46 +0300 Subject: [PATCH 209/256] [6917] Fix field multiplier ad load Arena Info. patch from killdozer. Signed-off-by: DiSlord --- src/game/Player.cpp | 12 ++++++------ src/shared/revision_nr.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 5a5fd6450..186ca32a3 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -13392,12 +13392,12 @@ void Player::_LoadArenaTeamInfo(QueryResult *result) ArenaTeam* aTeam = objmgr.GetArenaTeamById(arenateamid); uint8 arenaSlot = aTeam->GetSlot(); - m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3] = arenateamid; // TeamID - m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 1] = ((aTeam->GetCaptain() == GetGUID()) ? (uint32)0 : (uint32)1); // Captain 0, member 1 - m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 2] = played_week; // Played Week - m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 3] = played_season; // Played Season - m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 4] = 0; // Unk - m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 3 + 5] = personal_rating; // Personal Rating + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6] = arenateamid; // TeamID + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 1] = ((aTeam->GetCaptain() == GetGUID()) ? (uint32)0 : (uint32)1); // Captain 0, member 1 + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 2] = played_week; // Played Week + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 3] = played_season; // Played Season + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 4] = 0; // Unk + m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6 + 5] = personal_rating; // Personal Rating }while (result->NextRow()); delete result; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 0ac441485..8d02552b4 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6916" + #define REVISION_NR "6917" #endif // __REVISION_NR_H__ From 684c386f3a86a32fdaaddc517c736d028e174fed Mon Sep 17 00:00:00 2001 From: DiSlord Date: Fri, 19 Dec 2008 03:08:10 +0300 Subject: [PATCH 210/256] [6918] Not use enchant m_amount as spell basepoint by default (only for random enchants) Signed-off-by: DiSlord --- src/game/Player.cpp | 4 ++-- src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 186ca32a3..eb6be05e5 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -11316,9 +11316,9 @@ void Player::ApplyEnchantment(Item *item,EnchantmentSlot slot,bool apply, bool a { if(apply) { - int32 basepoints = int32(enchant_amount); + int32 basepoints = 0; // Random Property Exist - try found basepoints for spell (basepoints depends from item suffix factor) - if (item->GetItemRandomPropertyId() !=0 && !enchant_amount) + if (item->GetItemRandomPropertyId()) { ItemRandomSuffixEntry const *item_rand = sItemRandomSuffixStore.LookupEntry(abs(item->GetItemRandomPropertyId())); if (item_rand) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 8d02552b4..73958c37a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6917" + #define REVISION_NR "6918" #endif // __REVISION_NR_H__ From 11c45937b325218a42012fbcb8da044543e95efe Mon Sep 17 00:00:00 2001 From: GriffonHeart Date: Fri, 19 Dec 2008 02:51:22 +0300 Subject: [PATCH 211/256] Implement quest completing at spell 53341, 53343 cast. Also implement item 38607 using cast. Signed-off-by: VladimirMangos --- src/game/SpellEffects.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 09236f84e..252aacbdf 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1169,6 +1169,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 @@ -4919,6 +4925,14 @@ void Spell::EffectScriptEffect(uint32 effIndex) break; } + case 51770: + { + if(!unitTarget) + return; + + unitTarget->CastSpell(unitTarget,51771,false); + break; + } } if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN ) From 162ca267f1d461cf396bd4f5e24db9e7b344e80c Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Fri, 19 Dec 2008 15:48:21 +0200 Subject: [PATCH 212/256] [6919] Fixed character rename at login and optimized the query. --- src/game/CharacterHandler.cpp | 43 +++++++++++++++-------------------- src/shared/revision_nr.h | 2 +- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index ecde680d9..9022a5c33 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -935,18 +935,28 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) return; } - CharacterDatabase.escape_string(newname); + std::string escaped_newname = newname; + CharacterDatabase.escape_string(escaped_newname); - CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack, GUID_LOPART(guid), newname, "SELECT guid, at_login, name FROM characters WHERE guid = '%u' XOR name = '%s'", GUID_LOPART(guid), newname.c_str()); + // make sure that the character belongs to the current account, that rename at login is enabled + // and that there is no character with the desired new name + CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack, + GetAccountId(), newname, + "SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')", + GUID_LOPART(guid), GetAccountId(), AT_LOGIN_RENAME, AT_LOGIN_RENAME, escaped_newname.c_str() + ); } void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uint32 accountId, std::string newname) { WorldSession * session = sWorld.FindSession(accountId); if(!session) + { + if(result) delete result; return; + } - if (!result || result->GetRowCount() != 1) + if (!result) { WorldPacket data(SMSG_CHAR_RENAME, 1); data << (uint8)CHAR_CREATE_ERROR; @@ -954,33 +964,16 @@ void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uin return; } - Field *fields = result->Fetch(); - uint32 guidLow = fields[0].GetUInt32(); + uint32 guidLow = result->Fetch()[0].GetUInt32(); uint64 guid = MAKE_NEW_GUID(guidLow, 0, HIGHGUID_PLAYER); - uint32 at_loginFlags = fields[1].GetUInt32(); - std::string oldname = fields[2].GetCppString(); + std::string oldname = result->Fetch()[1].GetCppString(); + delete result; - if(oldname == newname) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_CREATE_ERROR; - session->SendPacket( &data ); - return; - } - // we have to check character at_login_flag & AT_LOGIN_RENAME also (fake packets hehe) - if (!(at_loginFlags & AT_LOGIN_RENAME)) - { - WorldPacket data(SMSG_CHAR_RENAME, 1); - data << (uint8)CHAR_CREATE_ERROR; - session->SendPacket( &data ); - return; - } - - 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("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; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 73958c37a..33c84194a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6918" + #define REVISION_NR "6919" #endif // __REVISION_NR_H__ From 5ba37964808bc83621920a83c682146f65c2152b Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Fri, 19 Dec 2008 15:50:58 +0200 Subject: [PATCH 213/256] [6920] Cleaned up DatabaseImpl and added support for async queries with 3 parameters passed to the callback. --- src/shared/Database/Database.h | 14 ++ src/shared/Database/DatabaseImpl.h | 218 +++++++++++++------------- src/shared/Database/SqlDelayThread.h | 2 +- src/shared/Database/SqlOperations.cpp | 5 +- src/shared/Database/SqlOperations.h | 2 +- src/shared/revision_nr.h | 2 +- 6 files changed, 126 insertions(+), 117 deletions(-) diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index a62675c70..16fa0e901 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -55,27 +55,41 @@ class MANGOS_DLL_SPEC Database QueryResult* PQuery(const char *format,...) ATTR_PRINTF(2,3); /// Async queries and query holders, implemented in DatabaseImpl.h + + // Query / member template bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*), const char *sql); template bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql); template bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql); + template + bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql); + // Query / static template bool AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql); template bool AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql); + template + bool AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql); + // PQuery / member template bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) ATTR_PRINTF(4,5); template bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6); template bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6); + template + bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(5,6); + // PQuery / static template bool AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6); template bool AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6); + template + bool AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(5,6); template + // QueryHolder bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder); template bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1); diff --git a/src/shared/Database/DatabaseImpl.h b/src/shared/Database/DatabaseImpl.h index d3eae749a..1be9878e5 100644 --- a/src/shared/Database/DatabaseImpl.h +++ b/src/shared/Database/DatabaseImpl.h @@ -21,84 +21,114 @@ /// Function body definitions for the template function members of the Database class +#define ASYNC_QUERY_BODY(sql, queue_itr) \ + if (!sql) return false; \ + \ + QueryQueues::iterator queue_itr; \ + \ + { \ + ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); \ + queue_itr = m_queryQueues.find(queryThread); \ + if (queue_itr == m_queryQueues.end()) return false; \ + } + +#define ASYNC_PQUERY_BODY(format, szQuery) \ + if(!format) return false; \ + \ + char szQuery [MAX_QUERY_LEN]; \ + \ + { \ + va_list ap; \ + \ + va_start(ap, format); \ + int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); \ + va_end(ap); \ + \ + if(res==-1) \ + { \ + sLog.outError("SQL Query truncated (and not execute) for format: %s",format); \ + return false; \ + } \ + } + +#define ASYNC_DELAYHOLDER_BODY(holder, queue_itr) \ + if (!holder) return false; \ + \ + QueryQueues::iterator queue_itr; \ + \ + { \ + ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); \ + queue_itr = m_queryQueues.find(queryThread); \ + if (queue_itr == m_queryQueues.end()) return false; \ + } + +// -- Query / member -- + template bool Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*), const char *sql) { - if (!sql) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method), itr->second)); - return true; + ASYNC_QUERY_BODY(sql, itr) + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method), itr->second)); } template bool Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql) { - if (!sql) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1), itr->second)); - return true; + ASYNC_QUERY_BODY(sql, itr) + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1), itr->second)); } template bool Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) { - if (!sql) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1, param2), itr->second)); - return true; + ASYNC_QUERY_BODY(sql, itr) + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1, param2), itr->second)); } +template +bool +Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql) +{ + ASYNC_QUERY_BODY(sql, itr) + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1, param2, param3), itr->second)); +} + +// -- Query / static -- + template bool Database::AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql) { - if (!sql) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1), itr->second)); - return true; + ASYNC_QUERY_BODY(sql, itr) + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1), itr->second)); } template bool Database::AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) { - if (!sql) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1, param2), itr->second)); - return true; + ASYNC_QUERY_BODY(sql, itr) + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1, param2), itr->second)); } +template +bool +Database::AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql) +{ + ASYNC_QUERY_BODY(sql, itr) + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1, param2, param3), itr->second)); +} + +// -- PQuery / member -- + template bool Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) { - if(!format) return false; - - va_list ap; - char szQuery [MAX_QUERY_LEN]; - va_start(ap, format); - int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); - va_end(ap); - - if(res==-1) - { - sLog.outError("SQL Query truncated (and not execute) for format: %s",format); - return false; - } - + ASYNC_PQUERY_BODY(format, szQuery) return AsyncQuery(object, method, szQuery); } @@ -106,20 +136,7 @@ template bool Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) { - if(!format) return false; - - va_list ap; - char szQuery [MAX_QUERY_LEN]; - va_start(ap, format); - int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); - va_end(ap); - - if(res==-1) - { - sLog.outError("SQL Query truncated (and not execute) for format: %s",format); - return false; - } - + ASYNC_PQUERY_BODY(format, szQuery) return AsyncQuery(object, method, param1, szQuery); } @@ -127,41 +144,25 @@ template bool Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) { - if(!format) return false; - - va_list ap; - char szQuery [MAX_QUERY_LEN]; - va_start(ap, format); - int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); - va_end(ap); - - if(res==-1) - { - sLog.outError("SQL Query truncated (and not execute) for format: %s",format); - return false; - } - + ASYNC_PQUERY_BODY(format, szQuery) return AsyncQuery(object, method, param1, param2, szQuery); } +template +bool +Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) +{ + ASYNC_PQUERY_BODY(format, szQuery) + return AsyncQuery(object, method, param1, param2, param3, szQuery); +} + +// -- PQuery / static -- + template bool Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) { - if(!format) return false; - - va_list ap; - char szQuery [MAX_QUERY_LEN]; - va_start(ap, format); - int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); - va_end(ap); - - if(res==-1) - { - sLog.outError("SQL Query truncated (and not execute) for format: %s",format); - return false; - } - + ASYNC_PQUERY_BODY(format, szQuery) return AsyncQuery(method, param1, szQuery); } @@ -169,43 +170,36 @@ template bool Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) { - if(!format) return false; - - va_list ap; - char szQuery [MAX_QUERY_LEN]; - va_start(ap, format); - int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); - va_end(ap); - - if(res==-1) - { - sLog.outError("SQL Query truncated (and not execute) for format: %s",format); - return false; - } - + ASYNC_PQUERY_BODY(format, szQuery) return AsyncQuery(method, param1, param2, szQuery); } +template +bool +Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) +{ + ASYNC_PQUERY_BODY(format, szQuery) + return AsyncQuery(method, param1, param2, param3, szQuery); +} + +// -- QueryHolder -- + template bool Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder) { - if (!holder) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - holder->Execute(new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, holder), m_threadBody, itr->second); - return true; + ASYNC_DELAYHOLDER_BODY(holder, itr) + return holder->Execute(new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, holder), m_threadBody, itr->second); } template bool Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1) { - if (!holder) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - holder->Execute(new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, holder, param1), m_threadBody, itr->second); - return true; + ASYNC_DELAYHOLDER_BODY(holder, itr) + return holder->Execute(new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, holder, param1), m_threadBody, itr->second); } + +#undef ASYNC_QUERY_BODY +#undef ASYNC_PQUERY_BODY +#undef ASYNC_DELAYHOLDER_BODY \ No newline at end of file diff --git a/src/shared/Database/SqlDelayThread.h b/src/shared/Database/SqlDelayThread.h index d80098dab..7d3187a98 100644 --- a/src/shared/Database/SqlDelayThread.h +++ b/src/shared/Database/SqlDelayThread.h @@ -40,7 +40,7 @@ class SqlDelayThread : public ZThread::Runnable SqlDelayThread(Database* db); ///< Put sql statement to delay queue - inline void Delay(SqlOperation* sql) { m_sqlQueue.add(sql); } + inline 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 bc75c591e..70a1ff056 100644 --- a/src/shared/Database/SqlOperations.cpp +++ b/src/shared/Database/SqlOperations.cpp @@ -79,15 +79,16 @@ void SqlResultQueue::Update() } } -void SqlQueryHolder::Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue) +bool SqlQueryHolder::Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue) { if(!callback || !thread || !queue) - return; + return false; /// delay the execution of the queries, sync them with the delay thread /// which will in turn resync on execution (via the queue) and call back SqlQueryHolderEx *holderEx = new SqlQueryHolderEx(this, callback, queue); thread->Delay(holderEx); + return true; } bool SqlQueryHolder::SetQuery(size_t index, const char *sql) diff --git a/src/shared/Database/SqlOperations.h b/src/shared/Database/SqlOperations.h index a5aa9113f..41ae69edb 100644 --- a/src/shared/Database/SqlOperations.h +++ b/src/shared/Database/SqlOperations.h @@ -104,7 +104,7 @@ class SqlQueryHolder void SetSize(size_t size); QueryResult* GetResult(size_t index); void SetResult(size_t index, QueryResult *result); - void Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue); + bool Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue); }; class SqlQueryHolderEx : public SqlOperation diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 33c84194a..c05428b33 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6919" + #define REVISION_NR "6920" #endif // __REVISION_NR_H__ From 546df44169e03314853cc9cd14eb2a6bb49cf858 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 20 Dec 2008 03:00:47 +0300 Subject: [PATCH 214/256] [6921] Fixed level depend spell damage calculation (limit it to spell base - max level) Signed-off-by: DiSlord --- src/game/Unit.cpp | 9 ++++++--- src/shared/revision_nr.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 5925b21c4..86a0e29af 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9203,9 +9203,12 @@ int32 Unit::CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_inde uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0; - int32 level = int32(getLevel()) - int32(spellProto->spellLevel); - if (level > spellProto->maxLevel && spellProto->maxLevel > 0) - level = spellProto->maxLevel; + int32 level = int32(getLevel()); + if (level > (int32)spellProto->maxLevel && spellProto->maxLevel > 0) + level = (int32)spellProto->maxLevel; + else if (level < (int32)spellProto->baseLevel) + level = (int32)spellProto->baseLevel; + level-= (int32)spellProto->spellLevel; float basePointsPerLevel = spellProto->EffectRealPointsPerLevel[effect_index]; float randomPointsPerLevel = spellProto->EffectDicePerLevel[effect_index]; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c05428b33..056d7d999 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6920" + #define REVISION_NR "6921" #endif // __REVISION_NR_H__ From 9f2e089b424ff687a5fcfc72dc784a3a856169f3 Mon Sep 17 00:00:00 2001 From: freghar Date: Fri, 19 Dec 2008 23:25:20 +0100 Subject: [PATCH 215/256] [6922] Whitespace and newline fixes This should fix the GCC "no newline at end of file" warnings. Signed-off-by: freghar --- sql/updates/2008_11_11_02_mangos_scripts.sql | 10 +++++----- sql/updates/2008_11_14_01_mangos_scripts.sql | 10 +++++----- src/bindings/universal/ScriptMgr.h | 2 +- src/game/CharacterHandler.cpp | 2 +- src/game/ObjectMgr.cpp | 2 +- src/shared/Database/DatabaseImpl.h | 4 ++-- src/shared/revision_nr.h | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sql/updates/2008_11_11_02_mangos_scripts.sql b/sql/updates/2008_11_11_02_mangos_scripts.sql index a9fbd1036..b2d9fb147 100644 --- a/sql/updates/2008_11_11_02_mangos_scripts.sql +++ b/sql/updates/2008_11_11_02_mangos_scripts.sql @@ -2,20 +2,20 @@ ALTER TABLE db_version CHANGE COLUMN required_2008_11_11_01_mangos_db_script_str ALTER TABLE event_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE gameobject_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE quest_end_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE quest_start_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE spell_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; diff --git a/sql/updates/2008_11_14_01_mangos_scripts.sql b/sql/updates/2008_11_14_01_mangos_scripts.sql index ab51cf3d8..a2176b612 100644 --- a/sql/updates/2008_11_14_01_mangos_scripts.sql +++ b/sql/updates/2008_11_14_01_mangos_scripts.sql @@ -1,16 +1,16 @@ ALTER TABLE db_version CHANGE COLUMN required_2008_11_11_02_mangos_scripts required_2008_11_14_01_mangos_scripts bit; ALTER TABLE event_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE gameobject_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE quest_end_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE quest_start_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE spell_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; diff --git a/src/bindings/universal/ScriptMgr.h b/src/bindings/universal/ScriptMgr.h index 0b4605b5e..415aa23cc 100644 --- a/src/bindings/universal/ScriptMgr.h +++ b/src/bindings/universal/ScriptMgr.h @@ -68,7 +68,7 @@ struct Script CreatureAI* (*GetAI)(Creature *_Creature); InstanceData* (*GetInstanceData)(Map*); // ----------------------------------------- - + void registerSelf(); }; diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 9022a5c33..f16680b3c 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -942,7 +942,7 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) // and that there is no character with the desired new name CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack, GetAccountId(), newname, - "SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')", + "SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')", GUID_LOPART(guid), GetAccountId(), AT_LOGIN_RENAME, AT_LOGIN_RENAME, escaped_newname.c_str() ); } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 83b9d7d76..0b1c0d357 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -578,7 +578,7 @@ void ObjectMgr::LoadCreatureLocales() sLog.outString(); sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() ); } - + void ObjectMgr::LoadNpcOptionLocales() { mNpcOptionLocaleMap.clear(); // need for reload case diff --git a/src/shared/Database/DatabaseImpl.h b/src/shared/Database/DatabaseImpl.h index 1be9878e5..d7f8c43e2 100644 --- a/src/shared/Database/DatabaseImpl.h +++ b/src/shared/Database/DatabaseImpl.h @@ -96,7 +96,7 @@ Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamTyp return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1, param2, param3), itr->second)); } -// -- Query / static -- +// -- Query / static -- template bool @@ -202,4 +202,4 @@ Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, Sq #undef ASYNC_QUERY_BODY #undef ASYNC_PQUERY_BODY -#undef ASYNC_DELAYHOLDER_BODY \ No newline at end of file +#undef ASYNC_DELAYHOLDER_BODY diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 056d7d999..482bae0e8 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6921" + #define REVISION_NR "6922" #endif // __REVISION_NR_H__ From b8a4b6f522a930cf6dc7caea4ffe7b3b0c587d3c Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 20 Dec 2008 03:47:29 +0300 Subject: [PATCH 216/256] [6923] Fixed opcide table miscompilation at VC in x64 release mode. In 303 branch it showup as crash at most chat commands. --- src/game/Opcodes.h | 7 ++++++- src/shared/revision_nr.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index a706fdea8..15901e6d4 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -25,6 +25,12 @@ #include "Common.h" +// Note: this include need for be sure have full definition of class WorldSession +// if this class definition not complite then VS for x64 release use different size for +// struct OpcodeHandler in this header and Opcode.cpp and get totally wrong data from +// table opcodeTable in source when Opcode.h included but WorldSession.h not included +#include "WorldSession.h" + /// List of Opcodes enum Opcodes { @@ -1102,7 +1108,6 @@ enum SessionStatus STATUS_NEVER ///< Opcode not accepted from client (deprecated or server side only) }; -class WorldSession; class WorldPacket; struct OpcodeHandler diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 482bae0e8..eafc0b2c5 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6922" + #define REVISION_NR "6923" #endif // __REVISION_NR_H__ From 01257874148b7cac988308b235c23ff76185698e Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 20 Dec 2008 04:15:07 +0300 Subject: [PATCH 217/256] Added new AP, RAP, SPH damage depends for all found SPELL_EFFECT_SCHOOL_DAMAGE spells Signed-off-by: DiSlord --- src/game/SpellEffects.cpp | 88 ++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 10 deletions(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 252aacbdf..eb3d13556 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -342,6 +342,13 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) damage = 200; break; } + // Intercept (warrior spell trigger) + case 20253: + case 61491: + { + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.12f); + break; + } } break; } @@ -371,6 +378,12 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) 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 & 0x0000000000000400LL) + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f); + // Heroic Throw ${$m1+$AP*.50} + else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL) + damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f); break; } case SPELLFAMILY_WARLOCK: @@ -380,18 +393,20 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) { // 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); } break; } case SPELLFAMILY_DRUID: { // Ferocious Bite - if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual[0]==6587) + if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 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 @@ -493,13 +508,29 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) { 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 & 0x0000000000000008LL) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.02f); + } + // Instant Poison + else if(m_spellInfo->SpellFamilyFlags & 0x0000000000002000LL) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.10f); + } + // Wound Poison + else if(m_spellInfo->SpellFamilyFlags & 0x0000000010000000LL) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.04f); + } break; } case SPELLFAMILY_HUNTER: @@ -507,12 +538,17 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) // Mongoose Bite if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual[0]==342) { - damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2); + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); + } + // Counterattack + else if(m_spellInfo->SpellFamilyFlags & 0x0008000000000000LL) + { + damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2f); } // Arcane Shot else if((m_spellInfo->SpellFamilyFlags & 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) @@ -520,16 +556,16 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) 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); } - //Explosive Trap Effect + // Explosive Trap Effect else if(m_spellInfo->SpellFamilyFlags & 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 + // Judgement of Vengeance if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292) { uint32 stacks = 0; @@ -543,6 +579,38 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) else damage *= stacks; } + // Avenger's Shield ($m1+0.07*$SPH+0.07*$AP) + else if(m_spellInfo->SpellFamilyFlags & 0x0000000000004000LL) + { + 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); + } + // Exorcism ($m1+0.15*$SPH+0.15*$AP) + else if(m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL) + { + 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 Wrath ($m1+0.15*$SPH+0.15*$AP) + else if(m_spellInfo->SpellFamilyFlags & 0x0000008000000000LL) + { + 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); + } + // Holy Wrath ($m1+0.07*$SPH+0.07*$AP) + else if(m_spellInfo->SpellFamilyFlags & 0x0020000000000000LL) + { + 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); + } break; } } From 5f4d5533e7d9d6de3282b8a0dc1c5342cdb8a736 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 20 Dec 2008 04:19:46 +0300 Subject: [PATCH 218/256] Some check, comments in HandleDummyAuraProc Added new spell ranks for some shaman talent Signed-off-by: DiSlord --- src/game/Unit.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index d710d29ae..bb6c9e890 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -4698,7 +4698,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu { switch (dummySpell->Id) { - // Eye of Eye + // Eye for an Eye case 9799: case 25988: { @@ -5289,7 +5289,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu 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; @@ -5426,6 +5426,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } case SPELLFAMILY_PALADIN: { + // TODO: spell list, formula change in 3.0.3 // Seal of Righteousness - melee proc dummy if (dummySpell->SpellFamilyFlags&0x000000008000000LL && triggeredByAura->GetEffIndex()==0) { @@ -5524,7 +5525,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } break; } - //Seal of Vengeance + // TODO: fix basepoint calculation (changed in 3.0.3) + // Seal of Vengeance case 31801: { if(effIndex != 0) // effect 1,2 used by seal unleashing code @@ -5533,7 +5535,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu triggered_spell_id = 31803; break; } - // Spiritual Att. + // Spiritual Attunement case 31785: case 33776: { @@ -5717,7 +5719,7 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu } // Earth Shield - if(dummySpell->SpellFamilyFlags==0x40000000000LL) + if(dummySpell->SpellFamilyFlags & 0x0000040000000000LL) { if(GetTypeId() != TYPEID_PLAYER) return false; @@ -5755,6 +5757,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 @@ -5762,6 +5766,8 @@ 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; @@ -5780,11 +5786,6 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu if (procSpell->SpellFamilyFlags & 0x0000000000000002LL) ((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); From 70c2f2201a55b233e1d9415b0b95c2064b4ebc5e Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 20 Dec 2008 04:32:38 +0300 Subject: [PATCH 219/256] Fix mask typo from last commit --- src/game/SpellEffects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index eb3d13556..346eb6acf 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -382,7 +382,7 @@ void Spell::EffectSchoolDMG(uint32 effect_idx) else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL) damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.207f); // Heroic Throw ${$m1+$AP*.50} - else if(m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL) + else if(m_spellInfo->SpellFamilyFlags & 0x0000000100000000LL) damage+= uint32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.5f); break; } From 68a23f6587ebdf931c2d27f83a8ca723884d2202 Mon Sep 17 00:00:00 2001 From: GriffonHeart Date: Sat, 20 Dec 2008 07:48:56 +0300 Subject: [PATCH 220/256] Core DB data for new class creating. Signed-off-by: VladimirMangos --- sql/mangos.sql | 770 +++++++++++++++++- sql/wotlk_updates/13_mangos_item_template.sql | 2 + .../14_mangos_playercreateinfo.sql | 12 + .../15_mangos_playercreateinfo_action.sql | 78 ++ .../16_mangos_playercreateinfo_spell.sql | 684 ++++++++++++++++ 5 files changed, 1545 insertions(+), 1 deletion(-) create mode 100644 sql/wotlk_updates/13_mangos_item_template.sql create mode 100644 sql/wotlk_updates/14_mangos_playercreateinfo.sql create mode 100644 sql/wotlk_updates/15_mangos_playercreateinfo_action.sql create mode 100644 sql/wotlk_updates/16_mangos_playercreateinfo_spell.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 87cb16eff..636ecb353 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -1642,7 +1642,7 @@ CREATE TABLE `item_template` ( `area` mediumint(8) unsigned NOT NULL default '0', `Map` smallint(6) NOT NULL default '0', `BagFamily` mediumint(9) NOT NULL default '0', - `TotemCategory` tinyint(4) NOT NULL default '0', + `TotemCategory` mediumint(9) NOT NULL default '0', `socketColor_1` tinyint(4) NOT NULL default '0', `socketContent_1` mediumint(9) NOT NULL default '0', `socketColor_2` tinyint(4) NOT NULL default '0', @@ -9236,11 +9236,13 @@ INSERT INTO `playercreateinfo` VALUES (1,2,0,12,-8949,-132,84), (1,4,0,12,-8949,-132,84), (1,5,0,12,-8949,-132,84), +(1,6,609,4298,2355.84,-5664.77,426.028), (1,8,0,12,-8949,-132,84), (1,9,0,12,-8949,-132,84), (2,1,1,14,-618,-4251,39), (2,3,1,14,-618,-4251,39), (2,4,1,14,-618,-4251,39), +(2,6,609,4298,2358.44,-5666.9,426.023), (2,7,1,14,-618,-4251,39), (2,9,1,14,-618,-4251,39), (3,1,0,1,-6240,331,383), @@ -9248,40 +9250,48 @@ INSERT INTO `playercreateinfo` VALUES (3,3,0,1,-6240,331,383), (3,4,0,1,-6240,331,383), (3,5,0,1,-6240,331,383), +(3,6,609,4298,2358.44,-5666.9,426.023), (4,1,1,141,10311,832,1327), (4,3,1,141,10311,832,1327), (4,4,1,141,10311,832,1327), (4,5,1,141,10311,832,1327), +(4,6,609,4298,2356.21,-5662.21,426.026), (4,11,1,141,10311,832,1327), (5,1,0,85,1676,1677,122), (5,4,0,85,1676,1677,122), (5,5,0,85,1676,1677,122), (5,8,0,85,1676,1677,122), (5,9,0,85,1676,1677,122), +(5,6,609,4298,2356.21,-5662.21,426.026), (6,1,1,215,-2917,-257,53), (6,3,1,215,-2917,-257,53), +(6,6,609,4298,2358.17,-5663.21,426.027), (6,7,1,215,-2917,-257,53), (6,11,1,215,-2917,-257,53), (7,1,0,1,-6240,331,383), (7,4,0,1,-6340,331,383), +(7,6,609,4298,2355.05,-5661.7, 426.026), (7,8,0,1,-6340,331,383), (7,9,0,1,-6340,331,383), (8,1,1,14,-618,-4251,39), (8,3,1,14,-618,-4251,39), (8,4,1,14,-618,-4251,39), (8,5,1,14,-618,-4251,39), +(8,6,609,4298,2355.05,-5661.7, 426.026), (8,7,1,14,-618,-4251,39), (8,8,1,14,-618,-4251,39), (10,2,530,3431,10349.6,-6357.29,33.4026), (10,3,530,3431,10349.6,-6357.29,33.4026), (10,4,530,3431,10349.6,-6357.29,33.4026), (10,5,530,3431,10349.6,-6357.29,33.4026), +(10,6,609,4298,2355.84,-5664.77,426.028), (10,8,530,3431,10349.6,-6357.29,33.4026), (10,9,530,3431,10349.6,-6357.29,33.4026), (11,1,530,3526,-3961.64,-13931.2,100.615), (11,2,530,3526,-3961.64,-13931.2,100.615), (11,3,530,3526,-3961.64,-13931.2,100.615), (11,5,530,3526,-3961.64,-13931.2,100.615), +(11,6,609,4298,2358.17,-5663.21,426.027), (11,7,530,3526,-3961.64,-13931.2,100.615), (11,8,530,3526,-3961.64,-13931.2,100.615); /*!40000 ALTER TABLE `playercreateinfo` ENABLE KEYS */; @@ -9327,6 +9337,13 @@ INSERT INTO `playercreateinfo_action` VALUES (1,5,0,6603,0,0), (1,5,10,159,128,0), (1,5,11,2070,128,0), +(1,6,0,6603,0,0), +(1,6,1,49576,0,0), +(1,6,2,45477,0,0), +(1,6,3,45462,0,0), +(1,6,4,45902,0,0), +(1,6,5,47541,0,0), +(1,6,11,59752,0,0), (1,8,1,133,0,0), (1,8,2,168,0,0), (1,8,0,6603,0,0), @@ -9350,6 +9367,13 @@ INSERT INTO `playercreateinfo_action` VALUES (2,4,2,2098,0,0), (2,4,0,6603,0,0), (2,4,11,117,128,0), +(2,6,0,6603,0,0), +(2,6,1,49576,0,0), +(2,6,2,45477,0,0), +(2,6,3,45462,0,0), +(2,6,4,45902,0,0), +(2,6,5,47541,0,0), +(2,6,10,20572,0,0), (2,7,2,331,0,0), (2,7,1,403,0,0), (2,7,0,6603,0,0), @@ -9383,6 +9407,13 @@ INSERT INTO `playercreateinfo_action` VALUES (3,5,0,6603,0,0), (3,5,10,159,128,0), (3,5,11,4540,128,0), +(3,6,0,6603,0,0), +(3,6,1,49576,0,0), +(3,6,2,45477,0,0), +(3,6,3,45462,0,0), +(3,6,4,45902,0,0), +(3,6,5,47541,0,0), +(3,6,10,2481,0,0), (4,1,1,78,0,0), (4,1,0,6603,0,0), (4,1,11,117,128,0), @@ -9401,6 +9432,14 @@ INSERT INTO `playercreateinfo_action` VALUES (4,5,0,6603,0,0), (4,5,10,159,128,0), (4,5,11,2070,128,0), +(4,6,0,6603,0,0), +(4,6,1,49576,0,0), +(4,6,2,45477,0,0), +(4,6,3,45462,0,0), +(4,6,4,45902,0,0), +(4,6,5,47541,0,0), +(4,6,10,58984,0,0), +(4,6,83,58984,0,0), (4,11,1,5176,0,0), (4,11,2,5185,0,0), (4,11,0,6603,0,0), @@ -9419,6 +9458,13 @@ INSERT INTO `playercreateinfo_action` VALUES (5,5,1,585,0,0), (5,5,11,4604,128,0), (5,5,0,6603,0,0), +(5,6,0,6603,0,0), +(5,6,1,49576,0,0), +(5,6,2,45477,0,0), +(5,6,3,45462,0,0), +(5,6,4,45902,0,0), +(5,6,5,47541,0,0), +(5,6,10,20577,0,0), (5,8,11,4604,128,0), (5,8,10,159,128,0), (5,8,2,168,0,0), @@ -9439,6 +9485,14 @@ INSERT INTO `playercreateinfo_action` VALUES (6,3,3,20549,0,0), (6,3,11,117,128,0), (6,3,0,6603,0,0), +(6,6,0,6603,0,0), +(6,6,1,49576,0,0), +(6,6,2,45477,0,0), +(6,6,3,45462,0,0), +(6,6,4,45902,0,0), +(6,6,5,47541,0,0), +(6,6,10,20549,0,0), +(6,6,75,20549,0,0), (6,7,1,403,0,0), (6,7,10,159,128,0), (6,7,2,331,0,0), @@ -9459,6 +9513,18 @@ INSERT INTO `playercreateinfo_action` VALUES (7,4,1,1752,0,0), (7,4,2,2098,0,0), (7,4,0,6603,0,0), +(7,6,0,6603,0,0), +(7,6,1,49576,0,0), +(7,6,2,45477,0,0), +(7,6,3,45462,0,0), +(7,6,4,45902,0,0), +(7,6,5,47541,0,0), +(7,6,10,20589,0,0), +(7,6,72,6603,0,0), +(7,6,83,117,128,0), +(7,6,84,6603,0,0), +(7,6,96,6603,0,0), +(7,6,108,6603,0,0), (7,8,11,4536,128,0), (7,8,1,133,0,0), (7,8,2,168,0,0), @@ -9488,6 +9554,13 @@ INSERT INTO `playercreateinfo_action` VALUES (8,5,2,2050,0,0), (8,5,11,4540,128,0), (8,5,0,6603,0,0), +(8,6,0,6603,0,0), +(8,6,1,49576,0,0), +(8,6,2,45477,0,0), +(8,6,3,45462,0,0), +(8,6,4,45902,0,0), +(8,6,5,47541,0,0), +(8,6,10,50621,0,0), (8,7,1,403,0,0), (8,7,10,159,128,0), (8,7,2,331,0,0), @@ -9526,6 +9599,13 @@ INSERT INTO `playercreateinfo_action` VALUES (10,5,4,28730,0,0), (10,5,10,159,128,0), (10,5,11,20857,128,0), +(10,6,0,6603,0,0), +(10,6,1,49576,0,0), +(10,6,2,45477,0,0), +(10,6,3,45462,0,0), +(10,6,4,45902,0,0), +(10,6,5,47541,0,0), +(10,6,6,50613,0,0), (10,8,0,6603,0,0), (10,8,1,133,0,0), (10,8,2,168,0,0), @@ -9573,6 +9653,12 @@ INSERT INTO `playercreateinfo_action` VALUES (11,5,10,159,128,0), (11,5,11,4540,128,0), (11,5,83,4540,128,0), +(11,6,0,6603,0,0), +(11,6,1,49576,0,0), +(11,6,2,45477,0,0), +(11,6,3,45462,0,0), +(11,6,4,45902,0,0), +(11,6,5,47541,0,0), (11,7,0,6603,0,0), (11,7,1,403,0,0), (11,7,2,331,0,0), @@ -9788,6 +9874,75 @@ INSERT INTO `playercreateinfo_spell` VALUES (1,5,21652,'Closing',1), (1,5,22027,'Remove Insignia',1), (1,5,22810,'Opening - No Text',1), +(1,6,81,'Dodge',1), +(1,6,196,'One-Handed Axes',1), +(1,6,197,'Two-Handed Axes',1), +(1,6,200,'Polearms',1), +(1,6,201,'One-Handed Swords',1), +(1,6,202,'Two-Handed Swords',1), +(1,6,203,'Unarmed',1), +(1,6,204,'Defense',1), +(1,6,522,'SPELLDEFENSE (DND)',1), +(1,6,668,'Language Common',1), +(1,6,674,'Dual Wield',1), +(1,6,750,'Plate Mail',1), +(1,6,1843,'Disarm',1), +(1,6,2382,'Generic',1), +(1,6,2479,'Honorless Target',1), +(1,6,3050,'Detect',1), +(1,6,3127,'Parry',1), +(1,6,3275,'Linen Bandage',1), +(1,6,3276,'Heavy Linen Bandage',1), +(1,6,3277,'Wool Bandage',1), +(1,6,3278,'Heavy Wool Bandage',1), +(1,6,3365,'Opening',1), +(1,6,6233,'Closing',1), +(1,6,6246,'Closing',1), +(1,6,6247,'Opening',1), +(1,6,6477,'Opening',1), +(1,6,6478,'Opening',1), +(1,6,6603,'Attack',1), +(1,6,7266,'Duel',1), +(1,6,7267,'Grovel',1), +(1,6,7355,'Stuck',1), +(1,6,7928,'Silk Bandage',1), +(1,6,7929,'Heavy Silk Bandage',1), +(1,6,7934,'Anti-Venom',1), +(1,6,8386,'Attacking',1), +(1,6,8737,'Mail',1), +(1,6,9077,'Leather',1), +(1,6,9078,'Cloth',1), +(1,6,9125,'Generic',1), +(1,6,10840,'Mageweave Bandage',1), +(1,6,10841,'Heavy Mageweave Bandage',1), +(1,6,10846,'First Aid',1), +(1,6,18629,'Runecloth Bandage',1), +(1,6,18630,'Heavy Runecloth Bandage',1), +(1,6,20597,'Sword Specialization',1), +(1,6,20598,'The Human Spirit',1), +(1,6,20599,'Diplomacy',1), +(1,6,20864,'Mace Specialization',1), +(1,6,21651,'Opening',1), +(1,6,21652,'Closing',1), +(1,6,22027,'Remove Insignia',1), +(1,6,22810,'Opening - No Text',1), +(1,6,33391,'Journeyman Riding',1), +(1,6,45462,'Plague Strike',1), +(1,6,45477,'Icy Touch',1), +(1,6,45902,'Blood Strike',1), +(1,6,45903,'Offensive State (DND)',1), +(1,6,45927,'Summon Friend',1), +(1,6,47541,'Death Coil',1), +(1,6,48266,'Blood Presence',1), +(1,6,49410,'Forceful Deflection',1), +(1,6,49576,'Death Grip',1), +(1,6,52665,'Sigil',1), +(1,6,58985,'Perception',1), +(1,6,59752,'Every Man for Himself',1), +(1,6,59879,'Blood Plague',1), +(1,6,59921,'Frost Fever',1), +(1,6,61437,'Opening',1), +(1,6,61455,'Runic Focus',1), (1,8,81,'Dodge',1), (1,8,133,'Fireball',1), (1,8,168,'Frost Armor',1), @@ -9975,6 +10130,73 @@ INSERT INTO `playercreateinfo_spell` VALUES (2,4,21652,'Closing',1), (2,4,22027,'Remove Insignia',1), (2,4,22810,'Opening - No Text',1), +(2,6,81,'Dodge',1), +(2,6,196,'One-Handed Axes',1), +(2,6,197,'Two-Handed Axes',1), +(2,6,200,'Polearms',1), +(2,6,201,'One-Handed Swords',1), +(2,6,202,'Two-Handed Swords',1), +(2,6,203,'Unarmed',1), +(2,6,204,'Defense',1), +(2,6,522,'SPELLDEFENSE (DND)',1), +(2,6,669,'Language Orcish',1), +(2,6,674,'Dual Wield',1), +(2,6,750,'Plate Mail',1), +(2,6,1843,'Disarm',1), +(2,6,2382,'Generic',1), +(2,6,2479,'Honorless Target',1), +(2,6,3050,'Detect',1), +(2,6,3127,'Parry',1), +(2,6,3275,'Linen Bandage',1), +(2,6,3276,'Heavy Linen Bandage',1), +(2,6,3277,'Wool Bandage',1), +(2,6,3278,'Heavy Wool Bandage',1), +(2,6,3365,'Opening',1), +(2,6,6233,'Closing',1), +(2,6,6246,'Closing',1), +(2,6,6247,'Opening',1), +(2,6,6477,'Opening',1), +(2,6,6478,'Opening',1), +(2,6,6603,'Attack',1), +(2,6,7266,'Duel',1), +(2,6,7267,'Grovel',1), +(2,6,7355,'Stuck',1), +(2,6,7928,'Silk Bandage',1), +(2,6,7929,'Heavy Silk Bandage',1), +(2,6,7934,'Anti-Venom',1), +(2,6,8386,'Attacking',1), +(2,6,8737,'Mail',1), +(2,6,9077,'Leather',1), +(2,6,9078,'Cloth',1), +(2,6,9125,'Generic',1), +(2,6,10840,'Mageweave Bandage',1), +(2,6,10841,'Heavy Mageweave Bandage',1), +(2,6,10846,'First Aid',1), +(2,6,18629,'Runecloth Bandage',1), +(2,6,18630,'Heavy Runecloth Bandage',1), +(2,6,20572,'Blood Fury',1), +(2,6,20573,'Hardiness',1), +(2,6,20574,'Axe Specialization',1), +(2,6,21651,'Opening',1), +(2,6,21652,'Closing',1), +(2,6,22027,'Remove Insignia',1), +(2,6,22810,'Opening - No Text',1), +(2,6,33391,'Journeyman Riding',1), +(2,6,45462,'Plague Strike',1), +(2,6,45477,'Icy Touch',1), +(2,6,45902,'Blood Strike',1), +(2,6,45903,'Offensive State (DND)',1), +(2,6,45927,'Summon Friend',1), +(2,6,47541,'Death Coil',1), +(2,6,48266,'Blood Presence',1), +(2,6,49410,'Forceful Deflection',1), +(2,6,49576,'Death Grip',1), +(2,6,52665,'Sigil',1), +(2,6,54562,'Command',1), +(2,6,59879,'Blood Plague',1), +(2,6,59921,'Frost Fever',1), +(2,6,61437,'Opening',1), +(2,6,61455,'Runic Focus',1), (2,7,81,'Dodge',1), (2,7,107,'Block',1), (2,7,198,'One-Handed Maces',1), @@ -10240,6 +10462,75 @@ INSERT INTO `playercreateinfo_spell` VALUES (3,5,21652,'Closing',1), (3,5,22027,'Remove Insignia',1), (3,5,22810,'Opening - No Text',1), +(3,6,81,'Dodge',1), +(3,6,196,'One-Handed Axes',1), +(3,6,197,'Two-Handed Axes',1), +(3,6,200,'Polearms',1), +(3,6,201,'One-Handed Swords',1), +(3,6,202,'Two-Handed Swords',1), +(3,6,203,'Unarmed',1), +(3,6,204,'Defense',1), +(3,6,522,'SPELLDEFENSE (DND)',1), +(3,6,668,'Language Common',1), +(3,6,672,'Language Dwarven',1), +(3,6,674,'Dual Wield',1), +(3,6,750,'Plate Mail',1), +(3,6,1843,'Disarm',1), +(3,6,2382,'Generic',1), +(3,6,2479,'Honorless Target',1), +(3,6,2481,'Find Treasure',1), +(3,6,3050,'Detect',1), +(3,6,3127,'Parry',1), +(3,6,3275,'Linen Bandage',1), +(3,6,3276,'Heavy Linen Bandage',1), +(3,6,3277,'Wool Bandage',1), +(3,6,3278,'Heavy Wool Bandage',1), +(3,6,3365,'Opening',1), +(3,6,6233,'Closing',1), +(3,6,6246,'Closing',1), +(3,6,6247,'Opening',1), +(3,6,6477,'Opening',1), +(3,6,6478,'Opening',1), +(3,6,6603,'Attack',1), +(3,6,7266,'Duel',1), +(3,6,7267,'Grovel',1), +(3,6,7355,'Stuck',1), +(3,6,7928,'Silk Bandage',1), +(3,6,7929,'Heavy Silk Bandage',1), +(3,6,7934,'Anti-Venom',1), +(3,6,8386,'Attacking',1), +(3,6,8737,'Mail',1), +(3,6,9077,'Leather',1), +(3,6,9078,'Cloth',1), +(3,6,9125,'Generic',1), +(3,6,10840,'Mageweave Bandage',1), +(3,6,10841,'Heavy Mageweave Bandage',1), +(3,6,10846,'First Aid',1), +(3,6,18629,'Runecloth Bandage',1), +(3,6,18630,'Heavy Runecloth Bandage',1), +(3,6,20594,'Stoneform',1), +(3,6,20595,'Gun Specialization',1), +(3,6,20596,'Frost Resistance',1), +(3,6,21651,'Opening',1), +(3,6,21652,'Closing',1), +(3,6,22027,'Remove Insignia',1), +(3,6,22810,'Opening - No Text',1), +(3,6,33391,'Journeyman Riding',1), +(3,6,45462,'Plague Strike',1), +(3,6,45477,'Icy Touch',1), +(3,6,45902,'Blood Strike',1), +(3,6,45903,'Offensive State (DND)',1), +(3,6,45927,'Summon Friend',1), +(3,6,47541,'Death Coil',1), +(3,6,48266,'Blood Presence',1), +(3,6,49410,'Forceful Deflection',1), +(3,6,49576,'Death Grip',1), +(3,6,52665,'Sigil',1), +(3,6,59224,'Mace Specialization',1), +(3,6,59879,'Blood Plague',1), +(3,6,59921,'Frost Fever',1), +(3,6,61437,'Opening',1), +(3,6,61455,'Runic Focus',1), (4,1,78,'Heroic Strike',1), (4,1,81,'Dodge',1), (4,1,107,'Block',1), @@ -10399,6 +10690,74 @@ INSERT INTO `playercreateinfo_spell` VALUES (4,5,21652,'Closing',1), (4,5,22027,'Remove Insignia',1), (4,5,22810,'Opening - No Text',1), +(4,6,81,'Dodge',1), +(4,6,196,'One-Handed Axes',1), +(4,6,197,'Two-Handed Axes',1), +(4,6,200,'Polearms',1), +(4,6,201,'One-Handed Swords',1), +(4,6,202,'Two-Handed Swords',1), +(4,6,203,'Unarmed',1), +(4,6,204,'Defense',1), +(4,6,522,'SPELLDEFENSE (DND)',1), +(4,6,668,'Language Common',1), +(4,6,671,'Language Darnassian',1), +(4,6,674,'Dual Wield',1), +(4,6,750,'Plate Mail',1), +(4,6,1843,'Disarm',1), +(4,6,2382,'Generic',1), +(4,6,2479,'Honorless Target',1), +(4,6,3050,'Detect',1), +(4,6,3127,'Parry',1), +(4,6,3275,'Linen Bandage',1), +(4,6,3276,'Heavy Linen Bandage',1), +(4,6,3277,'Wool Bandage',1), +(4,6,3278,'Heavy Wool Bandage',1), +(4,6,3365,'Opening',1), +(4,6,6233,'Closing',1), +(4,6,6246,'Closing',1), +(4,6,6247,'Opening',1), +(4,6,6477,'Opening',1), +(4,6,6478,'Opening',1), +(4,6,6603,'Attack',1), +(4,6,7266,'Duel',1), +(4,6,7267,'Grovel',1), +(4,6,7355,'Stuck',1), +(4,6,7928,'Silk Bandage',1), +(4,6,7929,'Heavy Silk Bandage',1), +(4,6,7934,'Anti-Venom',1), +(4,6,8386,'Attacking',1), +(4,6,8737,'Mail',1), +(4,6,9077,'Leather',1), +(4,6,9078,'Cloth',1), +(4,6,9125,'Generic',1), +(4,6,10840,'Mageweave Bandage',1), +(4,6,10841,'Heavy Mageweave Bandage',1), +(4,6,10846,'First Aid',1), +(4,6,18629,'Runecloth Bandage',1), +(4,6,18630,'Heavy Runecloth Bandage',1), +(4,6,20582,'Quickness',1), +(4,6,20583,'Nature Resistance',1), +(4,6,20585,'Wisp Spirit',1), +(4,6,21651,'Opening',1), +(4,6,21652,'Closing',1), +(4,6,22027,'Remove Insignia',1), +(4,6,22810,'Opening - No Text',1), +(4,6,33391,'Journeyman Riding',1), +(4,6,45462,'Plague Strike',1), +(4,6,45477,'Icy Touch',1), +(4,6,45902,'Blood Strike',1), +(4,6,45903,'Offensive State (DND)',1), +(4,6,45927,'Summon Friend',1), +(4,6,47541,'Death Coil',1), +(4,6,48266,'Blood Presence',1), +(4,6,49410,'Forceful Deflection',1), +(4,6,49576,'Death Grip',1), +(4,6,52665,'Sigil',1), +(4,6,58984,'Shadowmeld',1), +(4,6,59879,'Blood Plague',1), +(4,6,59921,'Frost Fever',1), +(4,6,61437,'Opening',1), +(4,6,61455,'Runic Focus',1), (4,11,81,'Dodge',1), (4,11,203,'Unarmed',1), (4,11,204,'Defense',1), @@ -10564,6 +10923,74 @@ INSERT INTO `playercreateinfo_spell` VALUES (5,5,21652,'Closing',1), (5,5,22027,'Remove Insignia',1), (5,5,22810,'Opening - No Text',1), +(5,6,81,'Dodge',1), +(5,6,196,'One-Handed Axes',1), +(5,6,197,'Two-Handed Axes',1), +(5,6,200,'Polearms',1), +(5,6,201,'One-Handed Swords',1), +(5,6,202,'Two-Handed Swords',1), +(5,6,203,'Unarmed',1), +(5,6,204,'Defense',1), +(5,6,522,'SPELLDEFENSE (DND)',1), +(5,6,669,'Language Orcish',1), +(5,6,674,'Dual Wield',1), +(5,6,750,'Plate Mail',1), +(5,6,1843,'Disarm',1), +(5,6,2382,'Generic',1), +(5,6,2479,'Honorless Target',1), +(5,6,3050,'Detect',1), +(5,6,3127,'Parry',1), +(5,6,3275,'Linen Bandage',1), +(5,6,3276,'Heavy Linen Bandage',1), +(5,6,3277,'Wool Bandage',1), +(5,6,3278,'Heavy Wool Bandage',1), +(5,6,3365,'Opening',1), +(5,6,5227,'Underwater Breathing',1), +(5,6,6233,'Closing',1), +(5,6,6246,'Closing',1), +(5,6,6247,'Opening',1), +(5,6,6477,'Opening',1), +(5,6,6478,'Opening',1), +(5,6,6603,'Attack',1), +(5,6,7266,'Duel',1), +(5,6,7267,'Grovel',1), +(5,6,7355,'Stuck',1), +(5,6,7744,'Will of the Forsaken',1), +(5,6,7928,'Silk Bandage',1), +(5,6,7929,'Heavy Silk Bandage',1), +(5,6,7934,'Anti-Venom',1), +(5,6,8386,'Attacking',1), +(5,6,8737,'Mail',1), +(5,6,9077,'Leather',1), +(5,6,9078,'Cloth',1), +(5,6,9125,'Generic',1), +(5,6,10840,'Mageweave Bandage',1), +(5,6,10841,'Heavy Mageweave Bandage',1), +(5,6,10846,'First Aid',1), +(5,6,17737,'Language Gutterspeak',1), +(5,6,18629,'Runecloth Bandage',1), +(5,6,18630,'Heavy Runecloth Bandage',1), +(5,6,20577,'Cannibalize',1), +(5,6,20579,'Shadow Resistance',1), +(5,6,21651,'Opening',1), +(5,6,21652,'Closing',1), +(5,6,22027,'Remove Insignia',1), +(5,6,22810,'Opening - No Text',1), +(5,6,33391,'Journeyman Riding',1), +(5,6,45462,'Plague Strike',1), +(5,6,45477,'Icy Touch',1), +(5,6,45902,'Blood Strike',1), +(5,6,45903,'Offensive State (DND)',1), +(5,6,45927,'Summon Friend',1), +(5,6,47541,'Death Coil',1), +(5,6,48266,'Blood Presence',1), +(5,6,49410,'Forceful Deflection',1), +(5,6,49576,'Death Grip',1), +(5,6,52665,'Sigil',1), +(5,6,59879,'Blood Plague',1), +(5,6,59921,'Frost Fever',1), +(5,6,61437,'Opening',1), +(5,6,61455,'Runic Focus',1), (5,8,81,'Dodge',1), (5,8,133,'Fireball',1), (5,8,168,'Frost Armor',1), @@ -10716,6 +11143,74 @@ INSERT INTO `playercreateinfo_spell` VALUES (6,3,22810,'Opening - No Text',1), (6,3,24949,'Defensive State 2(DND)',1), (6,3,34082,'Advantaged State(DND)',1), +(6,6,81,'Dodge',1), +(6,6,196,'One-Handed Axes',1), +(6,6,197,'Two-Handed Axes',1), +(6,6,200,'Polearms',1), +(6,6,201,'One-Handed Swords',1), +(6,6,202,'Two-Handed Swords',1), +(6,6,203,'Unarmed',1), +(6,6,204,'Defense',1), +(6,6,522,'SPELLDEFENSE (DND)',1), +(6,6,669,'Language Orcish',1), +(6,6,670,'Language Taurahe',1), +(6,6,674,'Dual Wield',1), +(6,6,750,'Plate Mail',1), +(6,6,1843,'Disarm',1), +(6,6,2382,'Generic',1), +(6,6,2479,'Honorless Target',1), +(6,6,3050,'Detect',1), +(6,6,3127,'Parry',1), +(6,6,3275,'Linen Bandage',1), +(6,6,3276,'Heavy Linen Bandage',1), +(6,6,3277,'Wool Bandage',1), +(6,6,3278,'Heavy Wool Bandage',1), +(6,6,3365,'Opening',1), +(6,6,6233,'Closing',1), +(6,6,6246,'Closing',1), +(6,6,6247,'Opening',1), +(6,6,6477,'Opening',1), +(6,6,6478,'Opening',1), +(6,6,6603,'Attack',1), +(6,6,7266,'Duel',1), +(6,6,7267,'Grovel',1), +(6,6,7355,'Stuck',1), +(6,6,7928,'Silk Bandage',1), +(6,6,7929,'Heavy Silk Bandage',1), +(6,6,7934,'Anti-Venom',1), +(6,6,8386,'Attacking',1), +(6,6,8737,'Mail',1), +(6,6,9077,'Leather',1), +(6,6,9078,'Cloth',1), +(6,6,9125,'Generic',1), +(6,6,10840,'Mageweave Bandage',1), +(6,6,10841,'Heavy Mageweave Bandage',1), +(6,6,10846,'First Aid',1), +(6,6,18629,'Runecloth Bandage',1), +(6,6,18630,'Heavy Runecloth Bandage',1), +(6,6,20549,'War Stomp',1), +(6,6,20550,'Endurance',1), +(6,6,20551,'Nature Resistance',1), +(6,6,20552,'Cultivation',1), +(6,6,21651,'Opening',1), +(6,6,21652,'Closing',1), +(6,6,22027,'Remove Insignia',1), +(6,6,22810,'Opening - No Text',1), +(6,6,33391,'Journeyman Riding',1), +(6,6,45462,'Plague Strike',1), +(6,6,45477,'Icy Touch',1), +(6,6,45902,'Blood Strike',1), +(6,6,45903,'Offensive State (DND)',1), +(6,6,45927,'Summon Friend',1), +(6,6,47541,'Death Coil',1), +(6,6,48266,'Blood Presence',1), +(6,6,49410,'Forceful Deflection',1), +(6,6,49576,'Death Grip',1), +(6,6,52665,'Sigil',1), +(6,6,59879,'Blood Plague',1), +(6,6,59921,'Frost Fever',1), +(6,6,61437,'Opening',1), +(6,6,61455,'Runic Focus',1), (6,7,81,'Dodge',1), (6,7,107,'Block',1), (6,7,198,'One-Handed Maces',1), @@ -10883,6 +11378,74 @@ INSERT INTO `playercreateinfo_spell` VALUES (7,4,21652,'Closing',1), (7,4,22027,'Remove Insignia',1), (7,4,22810,'Opening - No Text',1), +(7,6,81,'Dodge',1), +(7,6,196,'One-Handed Axes',1), +(7,6,197,'Two-Handed Axes',1), +(7,6,200,'Polearms',1), +(7,6,201,'One-Handed Swords',1), +(7,6,202,'Two-Handed Swords',1), +(7,6,203,'Unarmed',1), +(7,6,204,'Defense',1), +(7,6,522,'SPELLDEFENSE (DND)',1), +(7,6,668,'Language Common',1), +(7,6,674,'Dual Wield',1), +(7,6,750,'Plate Mail',1), +(7,6,1843,'Disarm',1), +(7,6,2382,'Generic',1), +(7,6,2479,'Honorless Target',1), +(7,6,3050,'Detect',1), +(7,6,3127,'Parry',1), +(7,6,3275,'Linen Bandage',1), +(7,6,3276,'Heavy Linen Bandage',1), +(7,6,3277,'Wool Bandage',1), +(7,6,3278,'Heavy Wool Bandage',1), +(7,6,3365,'Opening',1), +(7,6,6233,'Closing',1), +(7,6,6246,'Closing',1), +(7,6,6247,'Opening',1), +(7,6,6477,'Opening',1), +(7,6,6478,'Opening',1), +(7,6,6603,'Attack',1), +(7,6,7266,'Duel',1), +(7,6,7267,'Grovel',1), +(7,6,7340,'Language Gnomish',1), +(7,6,7355,'Stuck',1), +(7,6,7928,'Silk Bandage',1), +(7,6,7929,'Heavy Silk Bandage',1), +(7,6,7934,'Anti-Venom',1), +(7,6,8386,'Attacking',1), +(7,6,8737,'Mail',1), +(7,6,9077,'Leather',1), +(7,6,9078,'Cloth',1), +(7,6,9125,'Generic',1), +(7,6,10840,'Mageweave Bandage',1), +(7,6,10841,'Heavy Mageweave Bandage',1), +(7,6,10846,'First Aid',1), +(7,6,18629,'Runecloth Bandage',1), +(7,6,18630,'Heavy Runecloth Bandage',1), +(7,6,20589,'Escape Artist',1), +(7,6,20591,'Expansive Mind',1), +(7,6,20592,'Arcane Resistance',1), +(7,6,20593,'Engineering Specialization',1), +(7,6,21651,'Opening',1), +(7,6,21652,'Closing',1), +(7,6,22027,'Remove Insignia',1), +(7,6,22810,'Opening - No Text',1), +(7,6,33391,'Journeyman Riding',1), +(7,6,45462,'Plague Strike',1), +(7,6,45477,'Icy Touch',1), +(7,6,45902,'Blood Strike',1), +(7,6,45903,'Offensive State (DND)',1), +(7,6,45927,'Summon Friend',1), +(7,6,47541,'Death Coil',1), +(7,6,48266,'Blood Presence',1), +(7,6,49410,'Forceful Deflection',1), +(7,6,49576,'Death Grip',1), +(7,6,52665,'Sigil',1), +(7,6,59879,'Blood Plague',1), +(7,6,59921,'Frost Fever',1), +(7,6,61437,'Opening',1), +(7,6,61455,'Runic Focus',1), (7,8,81,'Dodge',1), (7,8,133,'Fireball',1), (7,8,168,'Frost Armor',1), @@ -11113,6 +11676,76 @@ INSERT INTO `playercreateinfo_spell` VALUES (8,5,22027,'Remove Insignia',1), (8,5,22810,'Opening - No Text',1), (8,5,26290,'Bow Specialization',1), +(8,6,81,'Dodge',1), +(8,6,196,'One-Handed Axes',1), +(8,6,197,'Two-Handed Axes',1), +(8,6,200,'Polearms',1), +(8,6,201,'One-Handed Swords',1), +(8,6,202,'Two-Handed Swords',1), +(8,6,203,'Unarmed',1), +(8,6,204,'Defense',1), +(8,6,522,'SPELLDEFENSE (DND)',1), +(8,6,669,'Language Orcish',1), +(8,6,674,'Dual Wield',1), +(8,6,750,'Plate Mail',1), +(8,6,1843,'Disarm',1), +(8,6,2382,'Generic',1), +(8,6,2479,'Honorless Target',1), +(8,6,3050,'Detect',1), +(8,6,3127,'Parry',1), +(8,6,3275,'Linen Bandage',1), +(8,6,3276,'Heavy Linen Bandage',1), +(8,6,3277,'Wool Bandage',1), +(8,6,3278,'Heavy Wool Bandage',1), +(8,6,3365,'Opening',1), +(8,6,6233,'Closing',1), +(8,6,6246,'Closing',1), +(8,6,6247,'Opening',1), +(8,6,6477,'Opening',1), +(8,6,6478,'Opening',1), +(8,6,6603,'Attack',1), +(8,6,7266,'Duel',1), +(8,6,7267,'Grovel',1), +(8,6,7341,'Language Troll',1), +(8,6,7355,'Stuck',1), +(8,6,7928,'Silk Bandage',1), +(8,6,7929,'Heavy Silk Bandage',1), +(8,6,7934,'Anti-Venom',1), +(8,6,8386,'Attacking',1), +(8,6,8737,'Mail',1), +(8,6,9077,'Leather',1), +(8,6,9078,'Cloth',1), +(8,6,9125,'Generic',1), +(8,6,10840,'Mageweave Bandage',1), +(8,6,10841,'Heavy Mageweave Bandage',1), +(8,6,10846,'First Aid',1), +(8,6,18629,'Runecloth Bandage',1), +(8,6,18630,'Heavy Runecloth Bandage',1), +(8,6,20555,'Regeneration',1), +(8,6,20557,'Beast Slaying',1), +(8,6,20558,'Throwing Specialization',1), +(8,6,21651,'Opening',1), +(8,6,21652,'Closing',1), +(8,6,22027,'Remove Insignia',1), +(8,6,22810,'Opening - No Text',1), +(8,6,26290,'Bow Specialization',1), +(8,6,33391,'Journeyman Riding',1), +(8,6,45462,'Plague Strike',1), +(8,6,45477,'Icy Touch',1), +(8,6,45902,'Blood Strike',1), +(8,6,45903,'Offensive State (DND)',1), +(8,6,45927,'Summon Friend',1), +(8,6,47541,'Death Coil',1), +(8,6,48266,'Blood Presence',1), +(8,6,49410,'Forceful Deflection',1), +(8,6,49576,'Death Grip',1), +(8,6,50621,'Berserking',1), +(8,6,52665,'Sigil',1), +(8,6,58943,'Da Voodoo Shuffle',1), +(8,6,59879,'Blood Plague',1), +(8,6,59921,'Frost Fever',1), +(8,6,61437,'Opening',1), +(8,6,61455,'Runic Focus',1), (8,7,81,'Dodge',1), (8,7,107,'Block',1), (8,7,198,'One-Handed Maces',1), @@ -11338,6 +11971,73 @@ INSERT INTO `playercreateinfo_spell` VALUES (10,5,28730,'Arcane Torrent',1), (10,5,28734,'Mana Tap',1), (10,5,28877,'Arcane Affinity',1), +(10,6,81,'Dodge',1), +(10,6,196,'One-Handed Axes',1), +(10,6,197,'Two-Handed Axes',1), +(10,6,200,'Polearms',1), +(10,6,201,'One-Handed Swords',1), +(10,6,202,'Two-Handed Swords',1), +(10,6,203,'Unarmed',1), +(10,6,204,'Defense',1), +(10,6,522,'SPELLDEFENSE (DND)',1), +(10,6,669,'Language Orcish',1), +(10,6,674,'Dual Wield',1), +(10,6,750,'Plate Mail',1), +(10,6,813,'Language Thalassian',1), +(10,6,822,'Magic Resistance',1), +(10,6,1843,'Disarm',1), +(10,6,2382,'Generic',1), +(10,6,2479,'Honorless Target',1), +(10,6,3050,'Detect',1), +(10,6,3127,'Parry',1), +(10,6,3275,'Linen Bandage',1), +(10,6,3276,'Heavy Linen Bandage',1), +(10,6,3277,'Wool Bandage',1), +(10,6,3278,'Heavy Wool Bandage',1), +(10,6,3365,'Opening',1), +(10,6,6233,'Closing',1), +(10,6,6246,'Closing',1), +(10,6,6247,'Opening',1), +(10,6,6477,'Opening',1), +(10,6,6478,'Opening',1), +(10,6,6603,'Attack',1), +(10,6,7266,'Duel',1), +(10,6,7267,'Grovel',1), +(10,6,7355,'Stuck',1), +(10,6,7928,'Silk Bandage',1), +(10,6,7929,'Heavy Silk Bandage',1), +(10,6,7934,'Anti-Venom',1), +(10,6,8386,'Attacking',1), +(10,6,8737,'Mail',1), +(10,6,9077,'Leather',1), +(10,6,9078,'Cloth',1), +(10,6,9125,'Generic',1), +(10,6,10840,'Mageweave Bandage',1), +(10,6,10841,'Heavy Mageweave Bandage',1), +(10,6,10846,'First Aid',1), +(10,6,18629,'Runecloth Bandage',1), +(10,6,18630,'Heavy Runecloth Bandage',1), +(10,6,21651,'Opening',1), +(10,6,21652,'Closing',1), +(10,6,22027,'Remove Insignia',1), +(10,6,22810,'Opening - No Text',1), +(10,6,28877,'Arcane Affinity',1), +(10,6,33391,'Journeyman Riding',1), +(10,6,45462,'Plague Strike',1), +(10,6,45477,'Icy Touch',1), +(10,6,45902,'Blood Strike',1), +(10,6,45903,'Offensive State (DND)',1), +(10,6,45927,'Summon Friend',1), +(10,6,47541,'Death Coil',1), +(10,6,48266,'Blood Presence',1), +(10,6,49410,'Forceful Deflection',1), +(10,6,49576,'Death Grip',1), +(10,6,50613,'Arcane Torrent',1), +(10,6,52665,'Sigil',1), +(10,6,59879,'Blood Plague',1), +(10,6,59921,'Frost Fever',1), +(10,6,61437,'Opening',1), +(10,6,61455,'Runic Focus',1), (10,8,81,'Dodge',1), (10,8,133,'Fireball',1), (10,8,168,'Frost Armor',1), @@ -11564,6 +12264,74 @@ INSERT INTO `playercreateinfo_spell` VALUES (11,5,28878,'Inspiring Presence',1), (11,5,28880,'Gift of the Naaru',1), (11,5,29932,'Language Draenei',1), +(11,6,81,'Dodge',1), +(11,6,196,'One-Handed Axes',1), +(11,6,197,'Two-Handed Axes',1), +(11,6,200,'Polearms',1), +(11,6,201,'One-Handed Swords',1), +(11,6,202,'Two-Handed Swords',1), +(11,6,203,'Unarmed',1), +(11,6,204,'Defense',1), +(11,6,522,'SPELLDEFENSE (DND)',1), +(11,6,668,'Language Common',1), +(11,6,674,'Dual Wield',1), +(11,6,750,'Plate Mail',1), +(11,6,1843,'Disarm',1), +(11,6,2382,'Generic',1), +(11,6,2479,'Honorless Target',1), +(11,6,3050,'Detect',1), +(11,6,3127,'Parry',1), +(11,6,3275,'Linen Bandage',1), +(11,6,3276,'Heavy Linen Bandage',1), +(11,6,3277,'Wool Bandage',1), +(11,6,3278,'Heavy Wool Bandage',1), +(11,6,3365,'Opening',1), +(11,6,6233,'Closing',1), +(11,6,6246,'Closing',1), +(11,6,6247,'Opening',1), +(11,6,6477,'Opening',1), +(11,6,6478,'Opening',1), +(11,6,6562,'Heroic Presence',1), +(11,6,6603,'Attack',1), +(11,6,7266,'Duel',1), +(11,6,7267,'Grovel',1), +(11,6,7355,'Stuck',1), +(11,6,7928,'Silk Bandage',1), +(11,6,7929,'Heavy Silk Bandage',1), +(11,6,7934,'Anti-Venom',1), +(11,6,8386,'Attacking',1), +(11,6,8737,'Mail',1), +(11,6,9077,'Leather',1), +(11,6,9078,'Cloth',1), +(11,6,9125,'Generic',1), +(11,6,10840,'Mageweave Bandage',1), +(11,6,10841,'Heavy Mageweave Bandage',1), +(11,6,10846,'First Aid',1), +(11,6,18629,'Runecloth Bandage',1), +(11,6,18630,'Heavy Runecloth Bandage',1), +(11,6,21651,'Opening',1), +(11,6,21652,'Closing',1), +(11,6,22027,'Remove Insignia',1), +(11,6,22810,'Opening - No Text',1), +(11,6,28875,'Gemcutting',1), +(11,6,29932,'Language Draenei',1), +(11,6,33391,'Journeyman Riding',1), +(11,6,45462,'Plague Strike',1), +(11,6,45477,'Icy Touch',1), +(11,6,45902,'Blood Strike',1), +(11,6,45903,'Offensive State (DND)',1), +(11,6,45927,'Summon Friend',1), +(11,6,47541,'Death Coil',1), +(11,6,48266,'Blood Presence',1), +(11,6,49410,'Forceful Deflection',1), +(11,6,49576,'Death Grip',1), +(11,6,52665,'Sigil',1), +(11,6,59539,'Shadow Resistance',1), +(11,6,59545,'Gift of the Naaru',1), +(11,6,59879,'Blood Plague',1), +(11,6,59921,'Frost Fever',1), +(11,6,61437,'Opening',1), +(11,6,61455,'Runic Focus',1), (11,7,81,'Dodge',1), (11,7,107,'Block',1), (11,7,198,'One-Handed Maces',1), diff --git a/sql/wotlk_updates/13_mangos_item_template.sql b/sql/wotlk_updates/13_mangos_item_template.sql new file mode 100644 index 000000000..ae4b7ed07 --- /dev/null +++ b/sql/wotlk_updates/13_mangos_item_template.sql @@ -0,0 +1,2 @@ +ALTER TABLE `item_template` + CHANGE COLUMN `TotemCategory` `TotemCategory` mediumint(9) NOT NULL default '0'; diff --git a/sql/wotlk_updates/14_mangos_playercreateinfo.sql b/sql/wotlk_updates/14_mangos_playercreateinfo.sql new file mode 100644 index 000000000..0279a3311 --- /dev/null +++ b/sql/wotlk_updates/14_mangos_playercreateinfo.sql @@ -0,0 +1,12 @@ +DELETE FROM `playercreateinfo` WHERE class = 6; +INSERT INTO `playercreateinfo` VALUES +(1 ,6,609,4298,2355.84,-5664.77,426.028), +(2 ,6,609,4298,2358.44,-5666.9, 426.023), +(3 ,6,609,4298,2358.44,-5666.9, 426.023), +(4 ,6,609,4298,2356.21,-5662.21,426.026), +(5 ,6,609,4298,2356.21,-5662.21,426.026), +(6 ,6,609,4298,2358.17,-5663.21,426.027), +(7 ,6,609,4298,2355.05,-5661.7, 426.026), +(8 ,6,609,4298,2355.05,-5661.7, 426.026), +(10,6,609,4298,2355.84,-5664.77,426.028), +(11,6,609,4298,2358.17,-5663.21,426.027); diff --git a/sql/wotlk_updates/15_mangos_playercreateinfo_action.sql b/sql/wotlk_updates/15_mangos_playercreateinfo_action.sql new file mode 100644 index 000000000..c2b2e1045 --- /dev/null +++ b/sql/wotlk_updates/15_mangos_playercreateinfo_action.sql @@ -0,0 +1,78 @@ +DELETE FROM playercreateinfo_action WHERE class = 6; +INSERT INTO playercreateinfo_action VALUES +(1,6,0,6603,0,0), +(1,6,1,49576,0,0), +(1,6,2,45477,0,0), +(1,6,3,45462,0,0), +(1,6,4,45902,0,0), +(1,6,5,47541,0,0), +(1,6,11,59752,0,0), +(2,6,0,6603,0,0), +(2,6,1,49576,0,0), +(2,6,2,45477,0,0), +(2,6,3,45462,0,0), +(2,6,4,45902,0,0), +(2,6,5,47541,0,0), +(2,6,10,20572,0,0), +(3,6,0,6603,0,0), +(3,6,1,49576,0,0), +(3,6,2,45477,0,0), +(3,6,3,45462,0,0), +(3,6,4,45902,0,0), +(3,6,5,47541,0,0), +(3,6,10,2481,0,0), +(4,6,0,6603,0,0), +(4,6,1,49576,0,0), +(4,6,2,45477,0,0), +(4,6,3,45462,0,0), +(4,6,4,45902,0,0), +(4,6,5,47541,0,0), +(4,6,10,58984,0,0), +(4,6,83,58984,0,0), +(5,6,0,6603,0,0), +(5,6,1,49576,0,0), +(5,6,2,45477,0,0), +(5,6,3,45462,0,0), +(5,6,4,45902,0,0), +(5,6,5,47541,0,0), +(5,6,10,20577,0,0), +(6,6,0,6603,0,0), +(6,6,1,49576,0,0), +(6,6,2,45477,0,0), +(6,6,3,45462,0,0), +(6,6,4,45902,0,0), +(6,6,5,47541,0,0), +(6,6,10,20549,0,0), +(6,6,75,20549,0,0), +(7,6,0,6603,0,0), +(7,6,1,49576,0,0), +(7,6,2,45477,0,0), +(7,6,3,45462,0,0), +(7,6,4,45902,0,0), +(7,6,5,47541,0,0), +(7,6,10,20589,0,0), +(7,6,72,6603,0,0), +(7,6,83,117,128,0), +(7,6,84,6603,0,0), +(7,6,96,6603,0,0), +(7,6,108,6603,0,0), +(8,6,0,6603,0,0), +(8,6,1,49576,0,0), +(8,6,2,45477,0,0), +(8,6,3,45462,0,0), +(8,6,4,45902,0,0), +(8,6,5,47541,0,0), +(8,6,10,50621,0,0), +(10,6,0,6603,0,0), +(10,6,1,49576,0,0), +(10,6,2,45477,0,0), +(10,6,3,45462,0,0), +(10,6,4,45902,0,0), +(10,6,5,47541,0,0), +(10,6,6,50613,0,0), +(11,6,0,6603,0,0), +(11,6,1,49576,0,0), +(11,6,2,45477,0,0), +(11,6,3,45462,0,0), +(11,6,4,45902,0,0), +(11,6,5,47541,0,0); diff --git a/sql/wotlk_updates/16_mangos_playercreateinfo_spell.sql b/sql/wotlk_updates/16_mangos_playercreateinfo_spell.sql new file mode 100644 index 000000000..a36e8215d --- /dev/null +++ b/sql/wotlk_updates/16_mangos_playercreateinfo_spell.sql @@ -0,0 +1,684 @@ +DELETE FROM `playercreateinfo_spell` WHERE `class` = 6; +INSERT INTO `playercreateinfo_spell` VALUES +(1,6,81,'Dodge',1), +(1,6,196,'One-Handed Axes',1), +(1,6,197,'Two-Handed Axes',1), +(1,6,200,'Polearms',1), +(1,6,201,'One-Handed Swords',1), +(1,6,202,'Two-Handed Swords',1), +(1,6,203,'Unarmed',1), +(1,6,204,'Defense',1), +(1,6,522,'SPELLDEFENSE (DND)',1), +(1,6,668,'Language Common',1), +(1,6,674,'Dual Wield',1), +(1,6,750,'Plate Mail',1), +(1,6,1843,'Disarm',1), +(1,6,2382,'Generic',1), +(1,6,2479,'Honorless Target',1), +(1,6,3050,'Detect',1), +(1,6,3127,'Parry',1), +(1,6,3275,'Linen Bandage',1), +(1,6,3276,'Heavy Linen Bandage',1), +(1,6,3277,'Wool Bandage',1), +(1,6,3278,'Heavy Wool Bandage',1), +(1,6,3365,'Opening',1), +(1,6,6233,'Closing',1), +(1,6,6246,'Closing',1), +(1,6,6247,'Opening',1), +(1,6,6477,'Opening',1), +(1,6,6478,'Opening',1), +(1,6,6603,'Attack',1), +(1,6,7266,'Duel',1), +(1,6,7267,'Grovel',1), +(1,6,7355,'Stuck',1), +(1,6,7928,'Silk Bandage',1), +(1,6,7929,'Heavy Silk Bandage',1), +(1,6,7934,'Anti-Venom',1), +(1,6,8386,'Attacking',1), +(1,6,8737,'Mail',1), +(1,6,9077,'Leather',1), +(1,6,9078,'Cloth',1), +(1,6,9125,'Generic',1), +(1,6,10840,'Mageweave Bandage',1), +(1,6,10841,'Heavy Mageweave Bandage',1), +(1,6,10846,'First Aid',1), +(1,6,18629,'Runecloth Bandage',1), +(1,6,18630,'Heavy Runecloth Bandage',1), +(1,6,20597,'Sword Specialization',1), +(1,6,20598,'The Human Spirit',1), +(1,6,20599,'Diplomacy',1), +(1,6,20864,'Mace Specialization',1), +(1,6,21651,'Opening',1), +(1,6,21652,'Closing',1), +(1,6,22027,'Remove Insignia',1), +(1,6,22810,'Opening - No Text',1), +(1,6,33391,'Journeyman Riding',1), +(1,6,45462,'Plague Strike',1), +(1,6,45477,'Icy Touch',1), +(1,6,45902,'Blood Strike',1), +(1,6,45903,'Offensive State (DND)',1), +(1,6,45927,'Summon Friend',1), +(1,6,47541,'Death Coil',1), +(1,6,48266,'Blood Presence',1), +(1,6,49410,'Forceful Deflection',1), +(1,6,49576,'Death Grip',1), +(1,6,52665,'Sigil',1), +(1,6,58985,'Perception',1), +(1,6,59752,'Every Man for Himself',1), +(1,6,59879,'Blood Plague',1), +(1,6,59921,'Frost Fever',1), +(1,6,61437,'Opening',1), +(1,6,61455,'Runic Focus',1), +(2,6,81,'Dodge',1), +(2,6,196,'One-Handed Axes',1), +(2,6,197,'Two-Handed Axes',1), +(2,6,200,'Polearms',1), +(2,6,201,'One-Handed Swords',1), +(2,6,202,'Two-Handed Swords',1), +(2,6,203,'Unarmed',1), +(2,6,204,'Defense',1), +(2,6,522,'SPELLDEFENSE (DND)',1), +(2,6,669,'Language Orcish',1), +(2,6,674,'Dual Wield',1), +(2,6,750,'Plate Mail',1), +(2,6,1843,'Disarm',1), +(2,6,2382,'Generic',1), +(2,6,2479,'Honorless Target',1), +(2,6,3050,'Detect',1), +(2,6,3127,'Parry',1), +(2,6,3275,'Linen Bandage',1), +(2,6,3276,'Heavy Linen Bandage',1), +(2,6,3277,'Wool Bandage',1), +(2,6,3278,'Heavy Wool Bandage',1), +(2,6,3365,'Opening',1), +(2,6,6233,'Closing',1), +(2,6,6246,'Closing',1), +(2,6,6247,'Opening',1), +(2,6,6477,'Opening',1), +(2,6,6478,'Opening',1), +(2,6,6603,'Attack',1), +(2,6,7266,'Duel',1), +(2,6,7267,'Grovel',1), +(2,6,7355,'Stuck',1), +(2,6,7928,'Silk Bandage',1), +(2,6,7929,'Heavy Silk Bandage',1), +(2,6,7934,'Anti-Venom',1), +(2,6,8386,'Attacking',1), +(2,6,8737,'Mail',1), +(2,6,9077,'Leather',1), +(2,6,9078,'Cloth',1), +(2,6,9125,'Generic',1), +(2,6,10840,'Mageweave Bandage',1), +(2,6,10841,'Heavy Mageweave Bandage',1), +(2,6,10846,'First Aid',1), +(2,6,18629,'Runecloth Bandage',1), +(2,6,18630,'Heavy Runecloth Bandage',1), +(2,6,20572,'Blood Fury',1), +(2,6,20573,'Hardiness',1), +(2,6,20574,'Axe Specialization',1), +(2,6,21651,'Opening',1), +(2,6,21652,'Closing',1), +(2,6,22027,'Remove Insignia',1), +(2,6,22810,'Opening - No Text',1), +(2,6,33391,'Journeyman Riding',1), +(2,6,45462,'Plague Strike',1), +(2,6,45477,'Icy Touch',1), +(2,6,45902,'Blood Strike',1), +(2,6,45903,'Offensive State (DND)',1), +(2,6,45927,'Summon Friend',1), +(2,6,47541,'Death Coil',1), +(2,6,48266,'Blood Presence',1), +(2,6,49410,'Forceful Deflection',1), +(2,6,49576,'Death Grip',1), +(2,6,52665,'Sigil',1), +(2,6,54562,'Command',1), +(2,6,59879,'Blood Plague',1), +(2,6,59921,'Frost Fever',1), +(2,6,61437,'Opening',1), +(2,6,61455,'Runic Focus',1), +(3,6,81,'Dodge',1), +(3,6,196,'One-Handed Axes',1), +(3,6,197,'Two-Handed Axes',1), +(3,6,200,'Polearms',1), +(3,6,201,'One-Handed Swords',1), +(3,6,202,'Two-Handed Swords',1), +(3,6,203,'Unarmed',1), +(3,6,204,'Defense',1), +(3,6,522,'SPELLDEFENSE (DND)',1), +(3,6,668,'Language Common',1), +(3,6,672,'Language Dwarven',1), +(3,6,674,'Dual Wield',1), +(3,6,750,'Plate Mail',1), +(3,6,1843,'Disarm',1), +(3,6,2382,'Generic',1), +(3,6,2479,'Honorless Target',1), +(3,6,2481,'Find Treasure',1), +(3,6,3050,'Detect',1), +(3,6,3127,'Parry',1), +(3,6,3275,'Linen Bandage',1), +(3,6,3276,'Heavy Linen Bandage',1), +(3,6,3277,'Wool Bandage',1), +(3,6,3278,'Heavy Wool Bandage',1), +(3,6,3365,'Opening',1), +(3,6,6233,'Closing',1), +(3,6,6246,'Closing',1), +(3,6,6247,'Opening',1), +(3,6,6477,'Opening',1), +(3,6,6478,'Opening',1), +(3,6,6603,'Attack',1), +(3,6,7266,'Duel',1), +(3,6,7267,'Grovel',1), +(3,6,7355,'Stuck',1), +(3,6,7928,'Silk Bandage',1), +(3,6,7929,'Heavy Silk Bandage',1), +(3,6,7934,'Anti-Venom',1), +(3,6,8386,'Attacking',1), +(3,6,8737,'Mail',1), +(3,6,9077,'Leather',1), +(3,6,9078,'Cloth',1), +(3,6,9125,'Generic',1), +(3,6,10840,'Mageweave Bandage',1), +(3,6,10841,'Heavy Mageweave Bandage',1), +(3,6,10846,'First Aid',1), +(3,6,18629,'Runecloth Bandage',1), +(3,6,18630,'Heavy Runecloth Bandage',1), +(3,6,20594,'Stoneform',1), +(3,6,20595,'Gun Specialization',1), +(3,6,20596,'Frost Resistance',1), +(3,6,21651,'Opening',1), +(3,6,21652,'Closing',1), +(3,6,22027,'Remove Insignia',1), +(3,6,22810,'Opening - No Text',1), +(3,6,33391,'Journeyman Riding',1), +(3,6,45462,'Plague Strike',1), +(3,6,45477,'Icy Touch',1), +(3,6,45902,'Blood Strike',1), +(3,6,45903,'Offensive State (DND)',1), +(3,6,45927,'Summon Friend',1), +(3,6,47541,'Death Coil',1), +(3,6,48266,'Blood Presence',1), +(3,6,49410,'Forceful Deflection',1), +(3,6,49576,'Death Grip',1), +(3,6,52665,'Sigil',1), +(3,6,59224,'Mace Specialization',1), +(3,6,59879,'Blood Plague',1), +(3,6,59921,'Frost Fever',1), +(3,6,61437,'Opening',1), +(3,6,61455,'Runic Focus',1), +(4,6,81,'Dodge',1), +(4,6,196,'One-Handed Axes',1), +(4,6,197,'Two-Handed Axes',1), +(4,6,200,'Polearms',1), +(4,6,201,'One-Handed Swords',1), +(4,6,202,'Two-Handed Swords',1), +(4,6,203,'Unarmed',1), +(4,6,204,'Defense',1), +(4,6,522,'SPELLDEFENSE (DND)',1), +(4,6,668,'Language Common',1), +(4,6,671,'Language Darnassian',1), +(4,6,674,'Dual Wield',1), +(4,6,750,'Plate Mail',1), +(4,6,1843,'Disarm',1), +(4,6,2382,'Generic',1), +(4,6,2479,'Honorless Target',1), +(4,6,3050,'Detect',1), +(4,6,3127,'Parry',1), +(4,6,3275,'Linen Bandage',1), +(4,6,3276,'Heavy Linen Bandage',1), +(4,6,3277,'Wool Bandage',1), +(4,6,3278,'Heavy Wool Bandage',1), +(4,6,3365,'Opening',1), +(4,6,6233,'Closing',1), +(4,6,6246,'Closing',1), +(4,6,6247,'Opening',1), +(4,6,6477,'Opening',1), +(4,6,6478,'Opening',1), +(4,6,6603,'Attack',1), +(4,6,7266,'Duel',1), +(4,6,7267,'Grovel',1), +(4,6,7355,'Stuck',1), +(4,6,7928,'Silk Bandage',1), +(4,6,7929,'Heavy Silk Bandage',1), +(4,6,7934,'Anti-Venom',1), +(4,6,8386,'Attacking',1), +(4,6,8737,'Mail',1), +(4,6,9077,'Leather',1), +(4,6,9078,'Cloth',1), +(4,6,9125,'Generic',1), +(4,6,10840,'Mageweave Bandage',1), +(4,6,10841,'Heavy Mageweave Bandage',1), +(4,6,10846,'First Aid',1), +(4,6,18629,'Runecloth Bandage',1), +(4,6,18630,'Heavy Runecloth Bandage',1), +(4,6,20582,'Quickness',1), +(4,6,20583,'Nature Resistance',1), +(4,6,20585,'Wisp Spirit',1), +(4,6,21651,'Opening',1), +(4,6,21652,'Closing',1), +(4,6,22027,'Remove Insignia',1), +(4,6,22810,'Opening - No Text',1), +(4,6,33391,'Journeyman Riding',1), +(4,6,45462,'Plague Strike',1), +(4,6,45477,'Icy Touch',1), +(4,6,45902,'Blood Strike',1), +(4,6,45903,'Offensive State (DND)',1), +(4,6,45927,'Summon Friend',1), +(4,6,47541,'Death Coil',1), +(4,6,48266,'Blood Presence',1), +(4,6,49410,'Forceful Deflection',1), +(4,6,49576,'Death Grip',1), +(4,6,52665,'Sigil',1), +(4,6,58984,'Shadowmeld',1), +(4,6,59879,'Blood Plague',1), +(4,6,59921,'Frost Fever',1), +(4,6,61437,'Opening',1), +(4,6,61455,'Runic Focus',1), +(5,6,81,'Dodge',1), +(5,6,196,'One-Handed Axes',1), +(5,6,197,'Two-Handed Axes',1), +(5,6,200,'Polearms',1), +(5,6,201,'One-Handed Swords',1), +(5,6,202,'Two-Handed Swords',1), +(5,6,203,'Unarmed',1), +(5,6,204,'Defense',1), +(5,6,522,'SPELLDEFENSE (DND)',1), +(5,6,669,'Language Orcish',1), +(5,6,674,'Dual Wield',1), +(5,6,750,'Plate Mail',1), +(5,6,1843,'Disarm',1), +(5,6,2382,'Generic',1), +(5,6,2479,'Honorless Target',1), +(5,6,3050,'Detect',1), +(5,6,3127,'Parry',1), +(5,6,3275,'Linen Bandage',1), +(5,6,3276,'Heavy Linen Bandage',1), +(5,6,3277,'Wool Bandage',1), +(5,6,3278,'Heavy Wool Bandage',1), +(5,6,3365,'Opening',1), +(5,6,5227,'Underwater Breathing',1), +(5,6,6233,'Closing',1), +(5,6,6246,'Closing',1), +(5,6,6247,'Opening',1), +(5,6,6477,'Opening',1), +(5,6,6478,'Opening',1), +(5,6,6603,'Attack',1), +(5,6,7266,'Duel',1), +(5,6,7267,'Grovel',1), +(5,6,7355,'Stuck',1), +(5,6,7744,'Will of the Forsaken',1), +(5,6,7928,'Silk Bandage',1), +(5,6,7929,'Heavy Silk Bandage',1), +(5,6,7934,'Anti-Venom',1), +(5,6,8386,'Attacking',1), +(5,6,8737,'Mail',1), +(5,6,9077,'Leather',1), +(5,6,9078,'Cloth',1), +(5,6,9125,'Generic',1), +(5,6,10840,'Mageweave Bandage',1), +(5,6,10841,'Heavy Mageweave Bandage',1), +(5,6,10846,'First Aid',1), +(5,6,17737,'Language Gutterspeak',1), +(5,6,18629,'Runecloth Bandage',1), +(5,6,18630,'Heavy Runecloth Bandage',1), +(5,6,20577,'Cannibalize',1), +(5,6,20579,'Shadow Resistance',1), +(5,6,21651,'Opening',1), +(5,6,21652,'Closing',1), +(5,6,22027,'Remove Insignia',1), +(5,6,22810,'Opening - No Text',1), +(5,6,33391,'Journeyman Riding',1), +(5,6,45462,'Plague Strike',1), +(5,6,45477,'Icy Touch',1), +(5,6,45902,'Blood Strike',1), +(5,6,45903,'Offensive State (DND)',1), +(5,6,45927,'Summon Friend',1), +(5,6,47541,'Death Coil',1), +(5,6,48266,'Blood Presence',1), +(5,6,49410,'Forceful Deflection',1), +(5,6,49576,'Death Grip',1), +(5,6,52665,'Sigil',1), +(5,6,59879,'Blood Plague',1), +(5,6,59921,'Frost Fever',1), +(5,6,61437,'Opening',1), +(5,6,61455,'Runic Focus',1), +(6,6,81,'Dodge',1), +(6,6,196,'One-Handed Axes',1), +(6,6,197,'Two-Handed Axes',1), +(6,6,200,'Polearms',1), +(6,6,201,'One-Handed Swords',1), +(6,6,202,'Two-Handed Swords',1), +(6,6,203,'Unarmed',1), +(6,6,204,'Defense',1), +(6,6,522,'SPELLDEFENSE (DND)',1), +(6,6,669,'Language Orcish',1), +(6,6,670,'Language Taurahe',1), +(6,6,674,'Dual Wield',1), +(6,6,750,'Plate Mail',1), +(6,6,1843,'Disarm',1), +(6,6,2382,'Generic',1), +(6,6,2479,'Honorless Target',1), +(6,6,3050,'Detect',1), +(6,6,3127,'Parry',1), +(6,6,3275,'Linen Bandage',1), +(6,6,3276,'Heavy Linen Bandage',1), +(6,6,3277,'Wool Bandage',1), +(6,6,3278,'Heavy Wool Bandage',1), +(6,6,3365,'Opening',1), +(6,6,6233,'Closing',1), +(6,6,6246,'Closing',1), +(6,6,6247,'Opening',1), +(6,6,6477,'Opening',1), +(6,6,6478,'Opening',1), +(6,6,6603,'Attack',1), +(6,6,7266,'Duel',1), +(6,6,7267,'Grovel',1), +(6,6,7355,'Stuck',1), +(6,6,7928,'Silk Bandage',1), +(6,6,7929,'Heavy Silk Bandage',1), +(6,6,7934,'Anti-Venom',1), +(6,6,8386,'Attacking',1), +(6,6,8737,'Mail',1), +(6,6,9077,'Leather',1), +(6,6,9078,'Cloth',1), +(6,6,9125,'Generic',1), +(6,6,10840,'Mageweave Bandage',1), +(6,6,10841,'Heavy Mageweave Bandage',1), +(6,6,10846,'First Aid',1), +(6,6,18629,'Runecloth Bandage',1), +(6,6,18630,'Heavy Runecloth Bandage',1), +(6,6,20549,'War Stomp',1), +(6,6,20550,'Endurance',1), +(6,6,20551,'Nature Resistance',1), +(6,6,20552,'Cultivation',1), +(6,6,21651,'Opening',1), +(6,6,21652,'Closing',1), +(6,6,22027,'Remove Insignia',1), +(6,6,22810,'Opening - No Text',1), +(6,6,33391,'Journeyman Riding',1), +(6,6,45462,'Plague Strike',1), +(6,6,45477,'Icy Touch',1), +(6,6,45902,'Blood Strike',1), +(6,6,45903,'Offensive State (DND)',1), +(6,6,45927,'Summon Friend',1), +(6,6,47541,'Death Coil',1), +(6,6,48266,'Blood Presence',1), +(6,6,49410,'Forceful Deflection',1), +(6,6,49576,'Death Grip',1), +(6,6,52665,'Sigil',1), +(6,6,59879,'Blood Plague',1), +(6,6,59921,'Frost Fever',1), +(6,6,61437,'Opening',1), +(6,6,61455,'Runic Focus',1), +(7,6,81,'Dodge',1), +(7,6,196,'One-Handed Axes',1), +(7,6,197,'Two-Handed Axes',1), +(7,6,200,'Polearms',1), +(7,6,201,'One-Handed Swords',1), +(7,6,202,'Two-Handed Swords',1), +(7,6,203,'Unarmed',1), +(7,6,204,'Defense',1), +(7,6,522,'SPELLDEFENSE (DND)',1), +(7,6,668,'Language Common',1), +(7,6,674,'Dual Wield',1), +(7,6,750,'Plate Mail',1), +(7,6,1843,'Disarm',1), +(7,6,2382,'Generic',1), +(7,6,2479,'Honorless Target',1), +(7,6,3050,'Detect',1), +(7,6,3127,'Parry',1), +(7,6,3275,'Linen Bandage',1), +(7,6,3276,'Heavy Linen Bandage',1), +(7,6,3277,'Wool Bandage',1), +(7,6,3278,'Heavy Wool Bandage',1), +(7,6,3365,'Opening',1), +(7,6,6233,'Closing',1), +(7,6,6246,'Closing',1), +(7,6,6247,'Opening',1), +(7,6,6477,'Opening',1), +(7,6,6478,'Opening',1), +(7,6,6603,'Attack',1), +(7,6,7266,'Duel',1), +(7,6,7267,'Grovel',1), +(7,6,7340,'Language Gnomish',1), +(7,6,7355,'Stuck',1), +(7,6,7928,'Silk Bandage',1), +(7,6,7929,'Heavy Silk Bandage',1), +(7,6,7934,'Anti-Venom',1), +(7,6,8386,'Attacking',1), +(7,6,8737,'Mail',1), +(7,6,9077,'Leather',1), +(7,6,9078,'Cloth',1), +(7,6,9125,'Generic',1), +(7,6,10840,'Mageweave Bandage',1), +(7,6,10841,'Heavy Mageweave Bandage',1), +(7,6,10846,'First Aid',1), +(7,6,18629,'Runecloth Bandage',1), +(7,6,18630,'Heavy Runecloth Bandage',1), +(7,6,20589,'Escape Artist',1), +(7,6,20591,'Expansive Mind',1), +(7,6,20592,'Arcane Resistance',1), +(7,6,20593,'Engineering Specialization',1), +(7,6,21651,'Opening',1), +(7,6,21652,'Closing',1), +(7,6,22027,'Remove Insignia',1), +(7,6,22810,'Opening - No Text',1), +(7,6,33391,'Journeyman Riding',1), +(7,6,45462,'Plague Strike',1), +(7,6,45477,'Icy Touch',1), +(7,6,45902,'Blood Strike',1), +(7,6,45903,'Offensive State (DND)',1), +(7,6,45927,'Summon Friend',1), +(7,6,47541,'Death Coil',1), +(7,6,48266,'Blood Presence',1), +(7,6,49410,'Forceful Deflection',1), +(7,6,49576,'Death Grip',1), +(7,6,52665,'Sigil',1), +(7,6,59879,'Blood Plague',1), +(7,6,59921,'Frost Fever',1), +(7,6,61437,'Opening',1), +(7,6,61455,'Runic Focus',1), +(8,6,81,'Dodge',1), +(8,6,196,'One-Handed Axes',1), +(8,6,197,'Two-Handed Axes',1), +(8,6,200,'Polearms',1), +(8,6,201,'One-Handed Swords',1), +(8,6,202,'Two-Handed Swords',1), +(8,6,203,'Unarmed',1), +(8,6,204,'Defense',1), +(8,6,522,'SPELLDEFENSE (DND)',1), +(8,6,669,'Language Orcish',1), +(8,6,674,'Dual Wield',1), +(8,6,750,'Plate Mail',1), +(8,6,1843,'Disarm',1), +(8,6,2382,'Generic',1), +(8,6,2479,'Honorless Target',1), +(8,6,3050,'Detect',1), +(8,6,3127,'Parry',1), +(8,6,3275,'Linen Bandage',1), +(8,6,3276,'Heavy Linen Bandage',1), +(8,6,3277,'Wool Bandage',1), +(8,6,3278,'Heavy Wool Bandage',1), +(8,6,3365,'Opening',1), +(8,6,6233,'Closing',1), +(8,6,6246,'Closing',1), +(8,6,6247,'Opening',1), +(8,6,6477,'Opening',1), +(8,6,6478,'Opening',1), +(8,6,6603,'Attack',1), +(8,6,7266,'Duel',1), +(8,6,7267,'Grovel',1), +(8,6,7341,'Language Troll',1), +(8,6,7355,'Stuck',1), +(8,6,7928,'Silk Bandage',1), +(8,6,7929,'Heavy Silk Bandage',1), +(8,6,7934,'Anti-Venom',1), +(8,6,8386,'Attacking',1), +(8,6,8737,'Mail',1), +(8,6,9077,'Leather',1), +(8,6,9078,'Cloth',1), +(8,6,9125,'Generic',1), +(8,6,10840,'Mageweave Bandage',1), +(8,6,10841,'Heavy Mageweave Bandage',1), +(8,6,10846,'First Aid',1), +(8,6,18629,'Runecloth Bandage',1), +(8,6,18630,'Heavy Runecloth Bandage',1), +(8,6,20555,'Regeneration',1), +(8,6,20557,'Beast Slaying',1), +(8,6,20558,'Throwing Specialization',1), +(8,6,21651,'Opening',1), +(8,6,21652,'Closing',1), +(8,6,22027,'Remove Insignia',1), +(8,6,22810,'Opening - No Text',1), +(8,6,26290,'Bow Specialization',1), +(8,6,33391,'Journeyman Riding',1), +(8,6,45462,'Plague Strike',1), +(8,6,45477,'Icy Touch',1), +(8,6,45902,'Blood Strike',1), +(8,6,45903,'Offensive State (DND)',1), +(8,6,45927,'Summon Friend',1), +(8,6,47541,'Death Coil',1), +(8,6,48266,'Blood Presence',1), +(8,6,49410,'Forceful Deflection',1), +(8,6,49576,'Death Grip',1), +(8,6,50621,'Berserking',1), +(8,6,52665,'Sigil',1), +(8,6,58943,'Da Voodoo Shuffle',1), +(8,6,59879,'Blood Plague',1), +(8,6,59921,'Frost Fever',1), +(8,6,61437,'Opening',1), +(8,6,61455,'Runic Focus',1), +(10,6,81,'Dodge',1), +(10,6,196,'One-Handed Axes',1), +(10,6,197,'Two-Handed Axes',1), +(10,6,200,'Polearms',1), +(10,6,201,'One-Handed Swords',1), +(10,6,202,'Two-Handed Swords',1), +(10,6,203,'Unarmed',1), +(10,6,204,'Defense',1), +(10,6,522,'SPELLDEFENSE (DND)',1), +(10,6,669,'Language Orcish',1), +(10,6,674,'Dual Wield',1), +(10,6,750,'Plate Mail',1), +(10,6,813,'Language Thalassian',1), +(10,6,822,'Magic Resistance',1), +(10,6,1843,'Disarm',1), +(10,6,2382,'Generic',1), +(10,6,2479,'Honorless Target',1), +(10,6,3050,'Detect',1), +(10,6,3127,'Parry',1), +(10,6,3275,'Linen Bandage',1), +(10,6,3276,'Heavy Linen Bandage',1), +(10,6,3277,'Wool Bandage',1), +(10,6,3278,'Heavy Wool Bandage',1), +(10,6,3365,'Opening',1), +(10,6,6233,'Closing',1), +(10,6,6246,'Closing',1), +(10,6,6247,'Opening',1), +(10,6,6477,'Opening',1), +(10,6,6478,'Opening',1), +(10,6,6603,'Attack',1), +(10,6,7266,'Duel',1), +(10,6,7267,'Grovel',1), +(10,6,7355,'Stuck',1), +(10,6,7928,'Silk Bandage',1), +(10,6,7929,'Heavy Silk Bandage',1), +(10,6,7934,'Anti-Venom',1), +(10,6,8386,'Attacking',1), +(10,6,8737,'Mail',1), +(10,6,9077,'Leather',1), +(10,6,9078,'Cloth',1), +(10,6,9125,'Generic',1), +(10,6,10840,'Mageweave Bandage',1), +(10,6,10841,'Heavy Mageweave Bandage',1), +(10,6,10846,'First Aid',1), +(10,6,18629,'Runecloth Bandage',1), +(10,6,18630,'Heavy Runecloth Bandage',1), +(10,6,21651,'Opening',1), +(10,6,21652,'Closing',1), +(10,6,22027,'Remove Insignia',1), +(10,6,22810,'Opening - No Text',1), +(10,6,28877,'Arcane Affinity',1), +(10,6,33391,'Journeyman Riding',1), +(10,6,45462,'Plague Strike',1), +(10,6,45477,'Icy Touch',1), +(10,6,45902,'Blood Strike',1), +(10,6,45903,'Offensive State (DND)',1), +(10,6,45927,'Summon Friend',1), +(10,6,47541,'Death Coil',1), +(10,6,48266,'Blood Presence',1), +(10,6,49410,'Forceful Deflection',1), +(10,6,49576,'Death Grip',1), +(10,6,50613,'Arcane Torrent',1), +(10,6,52665,'Sigil',1), +(10,6,59879,'Blood Plague',1), +(10,6,59921,'Frost Fever',1), +(10,6,61437,'Opening',1), +(10,6,61455,'Runic Focus',1), +(11,6,81,'Dodge',1), +(11,6,196,'One-Handed Axes',1), +(11,6,197,'Two-Handed Axes',1), +(11,6,200,'Polearms',1), +(11,6,201,'One-Handed Swords',1), +(11,6,202,'Two-Handed Swords',1), +(11,6,203,'Unarmed',1), +(11,6,204,'Defense',1), +(11,6,522,'SPELLDEFENSE (DND)',1), +(11,6,668,'Language Common',1), +(11,6,674,'Dual Wield',1), +(11,6,750,'Plate Mail',1), +(11,6,1843,'Disarm',1), +(11,6,2382,'Generic',1), +(11,6,2479,'Honorless Target',1), +(11,6,3050,'Detect',1), +(11,6,3127,'Parry',1), +(11,6,3275,'Linen Bandage',1), +(11,6,3276,'Heavy Linen Bandage',1), +(11,6,3277,'Wool Bandage',1), +(11,6,3278,'Heavy Wool Bandage',1), +(11,6,3365,'Opening',1), +(11,6,6233,'Closing',1), +(11,6,6246,'Closing',1), +(11,6,6247,'Opening',1), +(11,6,6477,'Opening',1), +(11,6,6478,'Opening',1), +(11,6,6562,'Heroic Presence',1), +(11,6,6603,'Attack',1), +(11,6,7266,'Duel',1), +(11,6,7267,'Grovel',1), +(11,6,7355,'Stuck',1), +(11,6,7928,'Silk Bandage',1), +(11,6,7929,'Heavy Silk Bandage',1), +(11,6,7934,'Anti-Venom',1), +(11,6,8386,'Attacking',1), +(11,6,8737,'Mail',1), +(11,6,9077,'Leather',1), +(11,6,9078,'Cloth',1), +(11,6,9125,'Generic',1), +(11,6,10840,'Mageweave Bandage',1), +(11,6,10841,'Heavy Mageweave Bandage',1), +(11,6,10846,'First Aid',1), +(11,6,18629,'Runecloth Bandage',1), +(11,6,18630,'Heavy Runecloth Bandage',1), +(11,6,21651,'Opening',1), +(11,6,21652,'Closing',1), +(11,6,22027,'Remove Insignia',1), +(11,6,22810,'Opening - No Text',1), +(11,6,28875,'Gemcutting',1), +(11,6,29932,'Language Draenei',1), +(11,6,33391,'Journeyman Riding',1), +(11,6,45462,'Plague Strike',1), +(11,6,45477,'Icy Touch',1), +(11,6,45902,'Blood Strike',1), +(11,6,45903,'Offensive State (DND)',1), +(11,6,45927,'Summon Friend',1), +(11,6,47541,'Death Coil',1), +(11,6,48266,'Blood Presence',1), +(11,6,49410,'Forceful Deflection',1), +(11,6,49576,'Death Grip',1), +(11,6,52665,'Sigil',1), +(11,6,59539,'Shadow Resistance',1), +(11,6,59545,'Gift of the Naaru',1), +(11,6,59879,'Blood Plague',1), +(11,6,59921,'Frost Fever',1), +(11,6,61437,'Opening',1), +(11,6,61455,'Runic Focus',1); From 32204204a38606d45042c4a7f2924934927749e4 Mon Sep 17 00:00:00 2001 From: balrok Date: Sat, 20 Dec 2008 20:22:37 +0300 Subject: [PATCH 221/256] [6924] Faster guild-loading. Signed-off-by: VladimirMangos --- src/game/Guild.cpp | 33 +++++++++++++++++++++++---------- src/shared/revision_nr.h | 2 +- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index bf6a3ab18..5dd34b302 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -359,28 +359,41 @@ bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot) } else { - if(!objmgr.GetPlayerNameByGUID(guid, plName)) // player doesn't exist - return false; + QueryResult *result = CharacterDatabase.PQuery("SELECT name,data,zone,class FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); + if(!result) + return false; // player doesn't exist + + Field *fields = result->Fetch(); + + plName = fields[0].GetCppString(); + + Tokens data = StrSplit(fields[1].GetCppString(), " "); + plLevel = Player::GetUInt32ValueFromArray(data,UNIT_FIELD_LEVEL); + + plZone = fields[2].GetUInt32(); + plClass = fields[3].GetUInt32(); + delete result; - plLevel = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL, guid); if(plLevel<1||plLevel>STRONG_MAX_LEVEL) // can be at broken `data` field { sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`data`.",GUID_LOPART(guid)); return false; } - plZone = Player::GetZoneIdFromDB(guid); - QueryResult *result = CharacterDatabase.PQuery("SELECT class FROM characters WHERE guid='%u'", GUID_LOPART(guid)); - if(!result) - return false; - plClass = (*result)[0].GetUInt32(); + if(!plZone) + { + sLog.outError("Player (GUID: %u) has broken zone-data",GUID_LOPART(guid)); + //here it will also try the same, to get the zone from characters-table, but additional it tries to find + plZone = Player::GetZoneIdFromDB(guid); + //the zone through xy coords.. this is a bit redundant, but + //shouldn't be called often + } + if(plClass=MAX_CLASSES) // can be at broken `class` field { sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`.",GUID_LOPART(guid)); return false; } - - delete result; } memslot->name = plName; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index eafc0b2c5..7de18d1af 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6923" + #define REVISION_NR "6924" #endif // __REVISION_NR_H__ From 381e801b7c364f34ef9890d3513a1a93b5c72eb4 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 20 Dec 2008 21:41:01 +0300 Subject: [PATCH 222/256] Add SPELL_EFFECT_SCRIPT_EFFECT for Hunter 53209 Signed-off-by: DiSlord --- src/game/SpellEffects.cpp | 54 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 346eb6acf..143bd4d70 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -5002,8 +5002,60 @@ void Spell::EffectScriptEffect(uint32 effIndex) break; } } + if( m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER ) + { + switch(m_spellInfo->Id) + { + // Chimera Shot + case 53209: + { + 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->SetAuraDuration(aura->GetAuraMaxDuration()); + aura->SendAuraUpdate(false); - if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN ) + // 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; + } + } + else if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN ) { switch(m_spellInfo->SpellFamilyFlags) { From 98c2cc9e7bc20dc96b76b9f243eba27193f9451c Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 20 Dec 2008 22:28:52 +0300 Subject: [PATCH 223/256] * Remove/rename spell effects changed in 303 Signed-off-by: DiSlord --- src/game/SharedDefines.h | 8 ++++---- src/game/SpellEffects.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index d2185cc10..7f8e76bed 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -603,10 +603,10 @@ 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, diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 143bd4d70..928013854 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -144,10 +144,10 @@ 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 From b64a8bd3fea8660cbf47238e4654137a26b449ec Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 20 Dec 2008 22:46:11 +0300 Subject: [PATCH 224/256] Fix effect name from last commit --- src/game/SharedDefines.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 7f8e76bed..e7f80b6d0 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -561,7 +561,7 @@ enum SpellEffects SPELL_EFFECT_SUMMON_GUARDIAN = 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, @@ -650,7 +650,7 @@ 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, From 061e73492e9e87956339796088865e4a29141568 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 20 Dec 2008 23:33:35 +0300 Subject: [PATCH 225/256] Use MiscB as stat for SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT Signed-off-by: DiSlord --- src/game/Unit.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index bb6c9e890..c6a43788e 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -7633,14 +7633,8 @@ int32 Unit::SpellBaseDamageBonus(SpellSchoolMask schoolMask) { 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]); - + // stat used stored in miscValueB for this aura + Stats usedStat = Stats((*i)->GetMiscBValue()); DoneAdvertisedBenefit += int32(GetStat(usedStat) * (*i)->GetModifier()->m_amount / 100.0f); } } From 4090872bfaa037f5a66d24533a60282f8a0f356a Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 20 Dec 2008 23:56:58 +0300 Subject: [PATCH 226/256] Implement SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT aura Remove redurant check m_miscvalue on Intelect for SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT Signed-off-by: DiSlord --- src/game/SpellAuras.cpp | 24 +++++++++++++++--------- src/game/SpellAuras.h | 1 + src/game/StatSystem.cpp | 17 +++++++++++++---- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 4caac0d70..635a1ab76 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -224,7 +224,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 @@ -318,7 +318,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNULL, //265 unused &Aura::HandleNULL, //266 unused &Aura::HandleNULL, //267 some immunity? - &Aura::HandleNULL, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT + &Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT &Aura::HandleNULL, //269 ignore DR effects? &Aura::HandleNULL, //270 &Aura::HandleNULL, //271 increase damage done? @@ -5014,17 +5014,23 @@ void Aura::HandleAuraModRangedAttackPowerOfStatPercent(bool apply, bool Real) if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) return; - 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-intelect stats!"); - return; - } - // Recalculate bonus ((Player*)m_target)->UpdateAttackPowerAndDamage(true); } +void Aura::HandleAuraModAttackPowerOfStatPercent(bool apply, bool Real) +{ + // spells required only Real aura add/remove + if(!Real) + return; + + if(m_target->GetTypeId() == TYPEID_PLAYER && (m_target->getClassMask() & CLASSMASK_WAND_USERS)!=0) + return; + + // Recalculate bonus + ((Player*)m_target)->UpdateAttackPowerAndDamage(false); +} + /********************************/ /*** DAMAGE BONUS ***/ /********************************/ diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 2ad9dd3c4..69742887d 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -187,6 +187,7 @@ class MANGOS_DLL_SPEC Aura 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); diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index f7aadca8b..96b17da65 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -308,11 +308,20 @@ void Player::UpdateAttackPowerAndDamage(bool ranged ) float attPowerMod = GetModifierValue(unitMod, TOTAL_VALUE); //add dynamic flat mods - if( ranged && (getClassMask() & CLASSMASK_WAND_USERS)==0) + if ((getClassMask() & CLASSMASK_WAND_USERS)==0) { - 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)->GetModifier()->m_amount / 100.0f); + if( ranged ) + { + 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)->GetModifier()->m_amount / 100.0f); + } + else + { + AuraList const& mRAPbyIntellect = GetAurasByType(SPELL_AURA_MOD_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)->GetModifier()->m_amount / 100.0f); + } } float attPowerMultiplier = GetModifierValue(unitMod, TOTAL_PCT) - 1.0f; From 1358202da32470f964df36635af1c4fcf24ffef2 Mon Sep 17 00:00:00 2001 From: begemot Date: Sun, 21 Dec 2008 00:13:07 +0300 Subject: [PATCH 227/256] [6925] Correctly show loaded 100% for empty `playercreateinfo_item`. Signed-off-by: VladimirMangos --- src/game/ObjectMgr.cpp | 2 ++ src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 0b1c0d357..813bbbae5 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -2099,6 +2099,8 @@ void ObjectMgr::LoadPlayerInfo() { barGoLink bar( 1 ); + bar.step(); + sLog.outString(); sLog.outString( ">> Loaded %u custom player create items", count ); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 7de18d1af..aa66c94b6 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6924" + #define REVISION_NR "6925" #endif // __REVISION_NR_H__ From 237d470a5b764558cfbe0c433dd2eaa224c3332a Mon Sep 17 00:00:00 2001 From: megamage Date: Sun, 21 Dec 2008 01:44:22 +0300 Subject: [PATCH 228/256] [6926] Use buyout to buy an auction when the last bid is close to the buyout price. Signed-off-by: megamage Fixed cheating possibility with original patch changes. Signed-off-by: VladimirMangos --- src/game/AuctionHouse.cpp | 9 +++++++-- src/shared/revision_nr.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/game/AuctionHouse.cpp b/src/game/AuctionHouse.cpp index a674aefb8..f7eee07f1 100644 --- a/src/game/AuctionHouse.cpp +++ b/src/game/AuctionHouse.cpp @@ -365,10 +365,15 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) return; } - if (price < (auction->bid + objmgr.GetAuctionOutBid(auction->bid))) + // cheating + if(price <= auction->bid) + return; + + // price too low for next bid if not buyout + if ((price < auction->buyout || auction->buyout == 0) && + price < auction->bid + objmgr.GetAuctionOutBid(auction->bid)) { //auction has already higher bid, client tests it! - //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); return; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index aa66c94b6..101dc5fd9 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6925" + #define REVISION_NR "6926" #endif // __REVISION_NR_H__ From c1ae939fb1f0853f3d816eac77644be4ad470782 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 21 Dec 2008 04:40:40 +0300 Subject: [PATCH 229/256] Implement new mangos.conf setting HeroicCharactersPerRealm for set cstiom (default 1) amount heroic class chanarcters for account per realm. Note: set option to 0 disable heroic characters creating. Also non-player account not have now any limits (except 10 clinet limit) for heroic characters creating. --- src/game/CharacterHandler.cpp | 37 +++++++++++++++++++++++++------- src/game/Player.cpp | 5 +++++ src/game/World.cpp | 7 ++++++ src/game/World.h | 1 + src/mangosd/mangosd.conf.dist.in | 6 ++++++ 5 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 04f003fc6..903a4a082 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -308,6 +308,15 @@ 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; + } + bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER; uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); @@ -323,14 +332,20 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) Field* field = result2->Fetch(); uint8 acc_race = field[0].GetUInt32(); - if(class_ == CLASS_DEATH_KNIGHT) + if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) { uint8 acc_class = field[1].GetUInt32(); if(acc_class == CLASS_DEATH_KNIGHT) { - data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; - SendPacket( &data ); - return; + if(heroic_free_slots > 0) + --heroic_free_slots; + + if(heroic_free_slots==0) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket( &data ); + return; + } } } @@ -364,14 +379,20 @@ void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) if(!have_same_race) have_same_race = race_ == acc_race; - if(class_ == CLASS_DEATH_KNIGHT) + if(GetSecurity()==SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) { uint8 acc_class = field[1].GetUInt32(); if(acc_class == CLASS_DEATH_KNIGHT) { - data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; - SendPacket( &data ); - return; + if(heroic_free_slots > 0) + --heroic_free_slots; + + if(heroic_free_slots==0) + { + data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; + SendPacket( &data ); + return; + } } } } diff --git a/src/game/Player.cpp b/src/game/Player.cpp index deac9c543..259ec5f27 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -690,6 +690,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) { diff --git a/src/game/World.cpp b/src/game/World.cpp index d7ed8de6b..6fa9a3088 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -633,6 +633,13 @@ void World::LoadConfigSettings(bool reload) m_configs[CONFIG_CHARACTERS_PER_REALM] = 10; } + 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; + } + // must be after CONFIG_CHARACTERS_PER_REALM m_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = sConfig.GetIntDefault("CharactersPerAccount", 50); if(m_configs[CONFIG_CHARACTERS_PER_ACCOUNT] < m_configs[CONFIG_CHARACTERS_PER_REALM]) diff --git a/src/game/World.h b/src/game/World.h index 9e5b2ad50..57167bf83 100644 --- a/src/game/World.h +++ b/src/game/World.h @@ -100,6 +100,7 @@ enum WorldConfigs CONFIG_CHARACTERS_CREATING_DISABLED, CONFIG_CHARACTERS_PER_ACCOUNT, CONFIG_CHARACTERS_PER_REALM, + CONFIG_HEROIC_CHARACTERS_PER_REALM, CONFIG_SKIP_CINEMATICS, CONFIG_MAX_PLAYER_LEVEL, CONFIG_START_PLAYER_LEVEL, diff --git a/src/mangosd/mangosd.conf.dist.in b/src/mangosd/mangosd.conf.dist.in index 08d0dbc01..2056bf98b 100644 --- a/src/mangosd/mangosd.conf.dist.in +++ b/src/mangosd/mangosd.conf.dist.in @@ -408,6 +408,11 @@ LogColors = "" # 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 +# # 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 @@ -574,6 +579,7 @@ StrictPetNames = 0 CharactersCreatingDisabled = 0 CharactersPerAccount = 50 CharactersPerRealm = 10 +HeroicCharactersPerRealm = 1 SkipCinematics = 0 MaxPlayerLevel = 80 StartPlayerLevel = 1 From d1a776f41a9d3d4275b44baf628a17f6290c89b1 Mon Sep 17 00:00:00 2001 From: GriffonHeart Date: Sun, 21 Dec 2008 04:45:42 +0300 Subject: [PATCH 230/256] New class starting items data for `item_template`. Signed-off-by: VladimirMangos --- sql/mangos.sql | 16 +++++++++++++++- sql/wotlk_updates/17_mangos_item_template.sql | 16 ++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 sql/wotlk_updates/17_mangos_item_template.sql diff --git a/sql/mangos.sql b/sql/mangos.sql index 636ecb353..6806c41f7 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -1743,7 +1743,21 @@ INSERT INTO `item_template` VALUES (14649,12,0,-1,'Valley of Trials Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5843,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (14650,12,0,-1,'Camp Narache Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5844,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), (14651,12,0,-1,'Deathknell Gift Voucher',18499,1,0,1,0,0,0,2047,255,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,'',0,0,0,5847,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), -(25861,2,16,-1,'Crude Throwing Axe',20777,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0); +(25861,2,16,-1,'Crude Throwing Axe',20777,1,0,1,15,0,25,2047,255,3,1,0,0,0,0,0,0,0,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2000,4,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,'',0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,'internalItemHandler',0,0,0,0,0), +(34648,4,4,-1,'Acherus Knight\'s Greaves',51496,2,32768,1,51,10,8,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,10,7,12,3,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,392,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,55,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34649,4,4,-1,'Acherus Knight\'s Gauntlets',51498,2,32768,1,34,6,10,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,15,7,6,32,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,356,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34650,4,4,-1,'Acherus Knight\'s Tunic',51494,2,32768,1,69,13,5,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,20,7,11,32,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,570,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,115,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34651,4,4,-1,'Acherus Knight\'s Girdle',51497,2,32768,1,35,7,6,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,2,4,10,32,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,320,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34652,4,4,-1,'Acherus Knight\'s Hood',51495,2,32768,1,52,10,1,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,15,7,15,32,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,463,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,70,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34653,4,4,-1,'Acherus Knight\'s Wristguard',51500,2,32768,1,36,7,9,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,7,31,7,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34655,4,4,-1,'Acherus Knight\'s Pauldrons',51501,2,32768,1,54,10,3,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,9,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,427,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,70,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34656,4,4,-1,'Acherus Knight\'s Cover',51499,2,32768,1,73,14,7,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,13,3,10,7,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,499,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,85,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34657,4,0,-1,'Choker of Damnation',6539,2,32768,1,2303,575,2,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,9,7,8,31,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34658,4,0,-1,'Plague Band',963,2,32768,1,534,133,11,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,6,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34659,4,1,-1,'Acherus Knight\'s Shroud',49738,2,32768,1,31,6,16,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,2,4,12,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(38145,1,0,-1,'Deathweave Bag',1282,1,32768,1,0,0,18,-1,-1,35,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(38147,4,0,-1,'Corrupted Band',963,2,32768,1,534,133,11,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,6,32,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(41751,0,5,-1,'Black Mushroom',36728,1,0,1,100,5,0,-1,-1,65,55,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27094,0,-1,0,0,11,1000,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,'',0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0); /*!40000 ALTER TABLE `item_template` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/wotlk_updates/17_mangos_item_template.sql b/sql/wotlk_updates/17_mangos_item_template.sql new file mode 100644 index 000000000..3a46cba3e --- /dev/null +++ b/sql/wotlk_updates/17_mangos_item_template.sql @@ -0,0 +1,16 @@ +DELETE FROM item_template WHERE entry IN (34648,34649,34650,34651,34652,34653,34655,34656,34657,34658,34659,38145,38147,41751); +INSERT INTO item_template VALUES +(34648,4,4,-1,'Acherus Knight\'s Greaves',51496,2,32768,1,51,10,8,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,10,7,12,3,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,392,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,55,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34649,4,4,-1,'Acherus Knight\'s Gauntlets',51498,2,32768,1,34,6,10,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,15,7,6,32,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,356,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34650,4,4,-1,'Acherus Knight\'s Tunic',51494,2,32768,1,69,13,5,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,20,7,11,32,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,570,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,115,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34651,4,4,-1,'Acherus Knight\'s Girdle',51497,2,32768,1,35,7,6,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,2,4,10,32,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,320,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34652,4,4,-1,'Acherus Knight\'s Hood',51495,2,32768,1,52,10,1,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,15,7,15,32,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,463,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,70,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34653,4,4,-1,'Acherus Knight\'s Wristguard',51500,2,32768,1,36,7,9,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,7,31,7,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,40,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34655,4,4,-1,'Acherus Knight\'s Pauldrons',51501,2,32768,1,54,10,3,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,9,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,427,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,70,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34656,4,4,-1,'Acherus Knight\'s Cover',51499,2,32768,1,73,14,7,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,13,3,10,7,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,499,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,85,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34657,4,0,-1,'Choker of Damnation',6539,2,32768,1,2303,575,2,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,9,7,8,31,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34658,4,0,-1,'Plague Band',963,2,32768,1,534,133,11,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,6,7,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(34659,4,1,-1,'Acherus Knight\'s Shroud',49738,2,32768,1,31,6,16,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,2,4,12,7,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(38145,1,0,-1,'Deathweave Bag',1282,1,32768,1,0,0,18,-1,-1,35,0,0,0,0,0,0,0,0,0,1,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(38147,4,0,-1,'Corrupted Band',963,2,32768,1,534,133,11,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,11,3,6,32,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), +(41751,0,5,-1,'Black Mushroom',36728,1,0,1,100,5,0,-1,-1,65,55,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27094,0,-1,0,0,11,1000,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,'',0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0); From 18eeaa85dd2dba8dfe964195df8828f8497738c7 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sun, 21 Dec 2008 05:07:16 +0300 Subject: [PATCH 231/256] Implement 220 SPELL_AURA_MOD_RATING_FROM_STAT aura Recalculate Melee/Ranged/Spell Hit Chances (not apply/remove) for players Signed-off-by: DiSlord --- src/game/Player.cpp | 25 +++++++++++++++++------- src/game/Player.h | 5 +++++ src/game/SpellAuras.cpp | 37 ++++++++++++++++++++++++++++++++---- src/game/SpellAuras.h | 1 + src/game/StatSystem.cpp | 42 ++++++++++++++++++++++++++++++++++------- 5 files changed, 92 insertions(+), 18 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 259ec5f27..2446a1da3 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -411,6 +411,9 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this) m_auraBaseMod[i][PCT_MOD] = 1.0f; } + for (int i = 0; i < MAX_COMBAT_RATING; i++) + m_baseRatingValue[i] = 0; + // Honor System m_lastHonorUpdateTime = time(NULL); @@ -4541,7 +4544,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<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; @@ -4564,16 +4578,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) diff --git a/src/game/Player.h b/src/game/Player.h index 53d676b9d..0f15be30c 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1650,6 +1650,10 @@ class MANGOS_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); @@ -2287,6 +2291,7 @@ class MANGOS_DLL_SPEC Player : public Unit ActionButtonList m_actionButtons; float m_auraBaseMod[BASEMOD_END][MOD_END]; + int16 m_baseRatingValue[MAX_COMBAT_RATING]; SpellModList m_spellMods[MAX_SPELLMOD]; int32 m_SpellModRemoveCount; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 635a1ab76..125a8da38 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -270,7 +270,7 @@ 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, //223 Cold Stare @@ -4883,13 +4883,28 @@ void Aura::HandleAuraModCritPercent(bool apply, bool Real) void Aura::HandleModHitChance(bool apply, bool Real) { - 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); + 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 ? m_modifier.m_amount: (-m_modifier.m_amount); + 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) @@ -5455,6 +5470,20 @@ void Aura::HandleModRating(bool apply, bool Real) ((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) { if(!Real || m_target->GetTypeId() != TYPEID_PLAYER) diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 69742887d..b62470ac1 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -183,6 +183,7 @@ class MANGOS_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); diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index 96b17da65..e3b67e6d1 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -49,24 +49,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 intelect currently UpdateArmor(); //SPELL_AURA_MOD_RESISTANCE_OF_INTELLECT_PERCENT, only armor currently break; @@ -76,8 +69,25 @@ bool Player::UpdateStats(Stats stat) default: break; } + // Need update (exist AP from stat auras) + UpdateAttackPowerAndDamage(); + 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; } @@ -560,6 +570,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++) From b72b1a178500054edc5c4cfa264fbf05822252c5 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sun, 21 Dec 2008 05:07:58 +0300 Subject: [PATCH 232/256] Add name for 194 SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL --- src/game/SpellAuraDefines.h | 2 +- src/game/SpellAuras.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 80b53f1a2..342987d57 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -236,7 +236,7 @@ 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_IGNORE_ABSORB_SCHOOL = 194, SPELL_AURA_MOD_DEPRICATED_2 = 195, // not used now, old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT SPELL_AURA_MOD_COOLDOWN = 196, // only 24818 Noxious Breath SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 125a8da38..3a36da8f0 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -244,7 +244,7 @@ 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, //194 SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL &Aura::HandleUnused, //195 SPELL_AURA_MOD_DEPRICATED_2 not used now (old SPELL_AURA_MOD_SPELL_HEALING_OF_INTELLECT) &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 From b646b327ce1fbebb5a68a6d39f1ba68e915e74d3 Mon Sep 17 00:00:00 2001 From: hunuza Date: Sun, 21 Dec 2008 14:42:18 +0100 Subject: [PATCH 233/256] [6927] Send correct level in error message due to too low level to create arena team. Signed-off-by: hunuza --- src/game/PetitionsHandler.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index 50eab90e4..3d525ac31 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -111,7 +111,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) // TODO: find correct opcode if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - SendNotification(LANG_ARENA_ONE_TOOLOW, 70); + SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); return; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 101dc5fd9..fcbcb4319 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6926" + #define REVISION_NR "6927" #endif // __REVISION_NR_H__ From 15d809e61df2c780021abc56ef0bba6ef7ecf2da Mon Sep 17 00:00:00 2001 From: DiSlord Date: Mon, 22 Dec 2008 01:43:23 +0300 Subject: [PATCH 234/256] Add/change some spell effect names, add/fix comments Signed-off-by: DiSlord --- src/game/SharedDefines.h | 11 ++++++----- src/game/SpellEffects.cpp | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index e7f80b6d0..882311934 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -582,14 +582,14 @@ enum SpellEffects SPELL_EFFECT_THREAT = 63, SPELL_EFFECT_TRIGGER_SPELL = 64, SPELL_EFFECT_APPLY_AREA_AURA_RAID = 65, - SPELL_EFFECT_POWER_FUNNEL = 66, + 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_UNTRAIN_TALENTS = 73, SPELL_EFFECT_APPLY_GLYPH = 74, SPELL_EFFECT_HEAL_MECHANICAL = 75, SPELL_EFFECT_SUMMON_OBJECT_WILD = 76, @@ -655,7 +655,7 @@ enum SpellEffects 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, @@ -704,7 +704,8 @@ enum AuraState 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_HYPOTHERMIA = 19, // c | + AURA_STATE_HEALTH_ABOVE_75_PERCENT = 23, // C | not implemented yet }; // Spell mechanics @@ -732,7 +733,7 @@ enum Mechanics MECHANIC_SHIELD = 19, MECHANIC_SHACKLE = 20, MECHANIC_MOUNT = 21, - MECHANIC_INFECTED = 22, //0 spells use this mechanic + MECHANIC_INFECTED = 22, MECHANIC_TURN = 23, MECHANIC_HORROR = 24, MECHANIC_INVULNERABILITY = 25, diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 928013854..9c1598038 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -123,14 +123,14 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectThreat, // 63 SPELL_EFFECT_THREAT &Spell::EffectTriggerSpell, // 64 SPELL_EFFECT_TRIGGER_SPELL &Spell::EffectApplyAreaAura, // 65 SPELL_EFFECT_APPLY_AREA_AURA_RAID - &Spell::EffectUnused, // 66 SPELL_EFFECT_POWER_FUNNEL unused + &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::EffectSummonGuardian, // 73 SPELL_EFFECT_SUMMON_POSSESSED + &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 @@ -189,14 +189,14 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectApplyAreaAura, //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY &Spell::EffectNULL, //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 From 8d4422239ec38126c9cca77fbed1cfea3571b6bf Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Mon, 22 Dec 2008 01:22:09 +0200 Subject: [PATCH 235/256] [6928] Corrected the handling of evade and threat for creature summoned pets. Should fix some of the setVisibility crashes. --- src/game/MotionMaster.cpp | 11 ++++++++++- src/game/Unit.cpp | 8 ++++++-- src/shared/revision_nr.h | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index 2dc42cd4d..23beef949 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -150,8 +150,17 @@ MotionMaster::MoveTargetedHome() } else if(i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID()) { - sLog.outError("Pet or controlled creature (Entry: %u GUID: %u) attempt targeted home", + DEBUG_LOG("Pet or controlled creature (Entry: %u GUID: %u) targeting home", i_owner->GetEntry(), i_owner->GetGUIDLow() ); + Unit *target = ((Creature*)i_owner)->GetCharmerOrOwner(); + if(target) + { + i_owner->addUnitState(UNIT_STAT_FOLLOW); + DEBUG_LOG("Following %s (GUID: %u)", + target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", + target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() ); + Mutate(new TargetedMovementGenerator(*target,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE)); + } } else { diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 86a0e29af..829555c2e 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9047,8 +9047,12 @@ bool Unit::CanHaveThreatList() const if( !isAlive() ) return false; - // pets and totems can not have threat list - if( ((Creature*)this)->isPet() || ((Creature*)this)->isTotem() ) + // totems can not have threat list + if( ((Creature*)this)->isTotem() ) + 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; return true; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index fcbcb4319..1a4a6befc 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6927" + #define REVISION_NR "6928" #endif // __REVISION_NR_H__ From 65339d1c0be7d2f48f036f83ece0043d6e73ae1e Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 22 Dec 2008 06:48:23 +0300 Subject: [PATCH 236/256] Restore build. --- src/game/Spell.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 5d5f6c87f..f94b22121 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -535,7 +535,6 @@ void Spell::FillTargetMap() case SPELL_EFFECT_LEARN_SPELL: case SPELL_EFFECT_SKILL_STEP: case SPELL_EFFECT_PROFICIENCY: - case SPELL_EFFECT_SUMMON_POSSESSED: case SPELL_EFFECT_SUMMON_OBJECT_WILD: case SPELL_EFFECT_SELF_RESURRECT: case SPELL_EFFECT_REPUTATION: @@ -4053,7 +4052,6 @@ uint8 Spell::CanCast(bool strict) } // 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: case SPELL_EFFECT_SUMMON_PHANTASM: case SPELL_EFFECT_SUMMON_DEMON: { From 1f7346813157ffee9611ddae40b1e0956448e731 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 22 Dec 2008 09:36:57 +0300 Subject: [PATCH 237/256] Small code cleanups. --- src/game/Bag.cpp | 2 +- src/game/Player.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/Bag.cpp b/src/game/Bag.cpp index cd6c4d69a..e0919ce36 100644 --- a/src/game/Bag.cpp +++ b/src/game/Bag.cpp @@ -32,7 +32,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/Player.cpp b/src/game/Player.cpp index 2446a1da3..baf042fad 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -13680,7 +13680,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; } From ba868910e21e357532a3b7ede6da1db94dce72a4 Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sat, 20 Dec 2008 03:00:47 +0300 Subject: [PATCH 238/256] [6921] Fixed level depend spell damage calculation (limit it to spell base - max level) Signed-off-by: DiSlord --- src/game/Unit.cpp | 9 ++++++--- src/shared/revision_nr.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index c6a43788e..5905df7cd 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9250,9 +9250,12 @@ int32 Unit::CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_inde uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0; - int32 level = int32(getLevel()) - int32(spellProto->spellLevel); - if (level > spellProto->maxLevel && spellProto->maxLevel > 0) - level = spellProto->maxLevel; + int32 level = int32(getLevel()); + if (level > (int32)spellProto->maxLevel && spellProto->maxLevel > 0) + level = (int32)spellProto->maxLevel; + else if (level < (int32)spellProto->baseLevel) + level = (int32)spellProto->baseLevel; + level-= (int32)spellProto->spellLevel; float basePointsPerLevel = spellProto->EffectRealPointsPerLevel[effect_index]; float randomPointsPerLevel = spellProto->EffectDicePerLevel[effect_index]; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c05428b33..056d7d999 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6920" + #define REVISION_NR "6921" #endif // __REVISION_NR_H__ From d75812749fd7e132caba67278225e3648f653478 Mon Sep 17 00:00:00 2001 From: freghar Date: Fri, 19 Dec 2008 23:25:20 +0100 Subject: [PATCH 239/256] [6922] Whitespace and newline fixes This should fix the GCC "no newline at end of file" warnings. Signed-off-by: freghar --- sql/updates/2008_11_11_02_mangos_scripts.sql | 10 +++++----- sql/updates/2008_11_14_01_mangos_scripts.sql | 10 +++++----- src/bindings/universal/ScriptMgr.h | 2 +- src/game/CharacterHandler.cpp | 2 +- src/game/ObjectMgr.cpp | 2 +- src/shared/Database/DatabaseImpl.h | 4 ++-- src/shared/revision_nr.h | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sql/updates/2008_11_11_02_mangos_scripts.sql b/sql/updates/2008_11_11_02_mangos_scripts.sql index a9fbd1036..b2d9fb147 100644 --- a/sql/updates/2008_11_11_02_mangos_scripts.sql +++ b/sql/updates/2008_11_11_02_mangos_scripts.sql @@ -2,20 +2,20 @@ ALTER TABLE db_version CHANGE COLUMN required_2008_11_11_01_mangos_db_script_str ALTER TABLE event_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE gameobject_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE quest_end_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE quest_start_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; ALTER TABLE spell_scripts DROP datatext, - ADD COLUMN dataint int(11) NOT NULL default '0'; + ADD COLUMN dataint int(11) NOT NULL default '0'; diff --git a/sql/updates/2008_11_14_01_mangos_scripts.sql b/sql/updates/2008_11_14_01_mangos_scripts.sql index ab51cf3d8..a2176b612 100644 --- a/sql/updates/2008_11_14_01_mangos_scripts.sql +++ b/sql/updates/2008_11_14_01_mangos_scripts.sql @@ -1,16 +1,16 @@ ALTER TABLE db_version CHANGE COLUMN required_2008_11_11_02_mangos_scripts required_2008_11_14_01_mangos_scripts bit; ALTER TABLE event_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE gameobject_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE quest_end_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE quest_start_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; ALTER TABLE spell_scripts - CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; + CHANGE COLUMN dataint dataint int(11) NOT NULL default '0' AFTER datalong2; diff --git a/src/bindings/universal/ScriptMgr.h b/src/bindings/universal/ScriptMgr.h index 0b4605b5e..415aa23cc 100644 --- a/src/bindings/universal/ScriptMgr.h +++ b/src/bindings/universal/ScriptMgr.h @@ -68,7 +68,7 @@ struct Script CreatureAI* (*GetAI)(Creature *_Creature); InstanceData* (*GetInstanceData)(Map*); // ----------------------------------------- - + void registerSelf(); }; diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index 903a4a082..b338c48af 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -984,7 +984,7 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) // and that there is no character with the desired new name CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack, GetAccountId(), newname, - "SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')", + "SELECT guid, name FROM characters WHERE guid = %d AND account = %d AND (at_login & %d) = %d AND NOT EXISTS (SELECT NULL FROM characters WHERE name = '%s')", GUID_LOPART(guid), GetAccountId(), AT_LOGIN_RENAME, AT_LOGIN_RENAME, escaped_newname.c_str() ); } diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 33137fdae..f25b93a46 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -579,7 +579,7 @@ void ObjectMgr::LoadCreatureLocales() sLog.outString(); sLog.outString( ">> Loaded %u creature locale strings", mCreatureLocaleMap.size() ); } - + void ObjectMgr::LoadCompletedAchievements() { QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); diff --git a/src/shared/Database/DatabaseImpl.h b/src/shared/Database/DatabaseImpl.h index 1be9878e5..d7f8c43e2 100644 --- a/src/shared/Database/DatabaseImpl.h +++ b/src/shared/Database/DatabaseImpl.h @@ -96,7 +96,7 @@ Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamTyp return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1, param2, param3), itr->second)); } -// -- Query / static -- +// -- Query / static -- template bool @@ -202,4 +202,4 @@ Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, Sq #undef ASYNC_QUERY_BODY #undef ASYNC_PQUERY_BODY -#undef ASYNC_DELAYHOLDER_BODY \ No newline at end of file +#undef ASYNC_DELAYHOLDER_BODY diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 056d7d999..482bae0e8 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6921" + #define REVISION_NR "6922" #endif // __REVISION_NR_H__ From 6d62e595b6fc3b0632c48b510929863b09cf13ca Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sat, 20 Dec 2008 03:47:29 +0300 Subject: [PATCH 240/256] [6923] Fixed opcide table miscompilation at VC in x64 release mode. In 303 branch it showup as crash at most chat commands. --- src/game/Opcodes.h | 7 ++++++- src/shared/revision_nr.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/game/Opcodes.h b/src/game/Opcodes.h index 7ea983757..124a03c68 100644 --- a/src/game/Opcodes.h +++ b/src/game/Opcodes.h @@ -25,6 +25,12 @@ #include "Common.h" +// Note: this include need for be sure have full definition of class WorldSession +// if this class definition not complite then VS for x64 release use different size for +// struct OpcodeHandler in this header and Opcode.cpp and get totally wrong data from +// table opcodeTable in source when Opcode.h included but WorldSession.h not included +#include "WorldSession.h" + /// List of Opcodes enum Opcodes { @@ -1230,7 +1236,6 @@ enum SessionStatus STATUS_NEVER ///< Opcode not accepted from client (deprecated or server side only) }; -class WorldSession; class WorldPacket; struct OpcodeHandler diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 482bae0e8..eafc0b2c5 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6922" + #define REVISION_NR "6923" #endif // __REVISION_NR_H__ From d4a69e478928d8d6c5c4dd9386765ee95c971c84 Mon Sep 17 00:00:00 2001 From: balrok Date: Sat, 20 Dec 2008 20:22:37 +0300 Subject: [PATCH 241/256] [6924] Faster guild-loading. Signed-off-by: VladimirMangos --- src/game/Guild.cpp | 33 +++++++++++++++++++++++---------- src/shared/revision_nr.h | 2 +- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/game/Guild.cpp b/src/game/Guild.cpp index ca6051f22..cedfc6e6a 100644 --- a/src/game/Guild.cpp +++ b/src/game/Guild.cpp @@ -359,28 +359,41 @@ bool Guild::FillPlayerData(uint64 guid, MemberSlot* memslot) } else { - if(!objmgr.GetPlayerNameByGUID(guid, plName)) // player doesn't exist - return false; + QueryResult *result = CharacterDatabase.PQuery("SELECT name,data,zone,class FROM characters WHERE guid = '%u'", GUID_LOPART(guid)); + if(!result) + return false; // player doesn't exist + + Field *fields = result->Fetch(); + + plName = fields[0].GetCppString(); + + Tokens data = StrSplit(fields[1].GetCppString(), " "); + plLevel = Player::GetUInt32ValueFromArray(data,UNIT_FIELD_LEVEL); + + plZone = fields[2].GetUInt32(); + plClass = fields[3].GetUInt32(); + delete result; - plLevel = Player::GetUInt32ValueFromDB(UNIT_FIELD_LEVEL, guid); if(plLevel<1||plLevel>STRONG_MAX_LEVEL) // can be at broken `data` field { sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`data`.",GUID_LOPART(guid)); return false; } - plZone = Player::GetZoneIdFromDB(guid); - QueryResult *result = CharacterDatabase.PQuery("SELECT class FROM characters WHERE guid='%u'", GUID_LOPART(guid)); - if(!result) - return false; - plClass = (*result)[0].GetUInt32(); + if(!plZone) + { + sLog.outError("Player (GUID: %u) has broken zone-data",GUID_LOPART(guid)); + //here it will also try the same, to get the zone from characters-table, but additional it tries to find + plZone = Player::GetZoneIdFromDB(guid); + //the zone through xy coords.. this is a bit redundant, but + //shouldn't be called often + } + if(plClass=MAX_CLASSES) // can be at broken `class` field { sLog.outError("Player (GUID: %u) has a broken data in field `characters`.`class`.",GUID_LOPART(guid)); return false; } - - delete result; } memslot->name = plName; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index eafc0b2c5..7de18d1af 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6923" + #define REVISION_NR "6924" #endif // __REVISION_NR_H__ From 128f8088584bc03c604bfe220ff80597063c3d05 Mon Sep 17 00:00:00 2001 From: begemot Date: Sun, 21 Dec 2008 00:13:07 +0300 Subject: [PATCH 242/256] [6925] Correctly show loaded 100% for empty `playercreateinfo_item`. Signed-off-by: VladimirMangos --- src/game/ObjectMgr.cpp | 2 ++ src/shared/revision_nr.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index f25b93a46..f0332aa00 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -2152,6 +2152,8 @@ void ObjectMgr::LoadPlayerInfo() { barGoLink bar( 1 ); + bar.step(); + sLog.outString(); sLog.outString( ">> Loaded %u custom player create items", count ); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 7de18d1af..aa66c94b6 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6924" + #define REVISION_NR "6925" #endif // __REVISION_NR_H__ From c7ba0afad4eef4f7dcc8ad4ee8d1ede5dea9ed4b Mon Sep 17 00:00:00 2001 From: megamage Date: Sun, 21 Dec 2008 01:44:22 +0300 Subject: [PATCH 243/256] [6926] Use buyout to buy an auction when the last bid is close to the buyout price. Signed-off-by: megamage Fixed cheating possibility with original patch changes. Signed-off-by: VladimirMangos --- src/game/AuctionHouse.cpp | 9 +++++++-- src/shared/revision_nr.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/game/AuctionHouse.cpp b/src/game/AuctionHouse.cpp index 4120d1818..8ec7d402d 100644 --- a/src/game/AuctionHouse.cpp +++ b/src/game/AuctionHouse.cpp @@ -365,10 +365,15 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) return; } - if (price < (auction->bid + objmgr.GetAuctionOutBid(auction->bid))) + // cheating + if(price <= auction->bid) + return; + + // price too low for next bid if not buyout + if ((price < auction->buyout || auction->buyout == 0) && + price < auction->bid + objmgr.GetAuctionOutBid(auction->bid)) { //auction has already higher bid, client tests it! - //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); return; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index aa66c94b6..101dc5fd9 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6925" + #define REVISION_NR "6926" #endif // __REVISION_NR_H__ From 1884889f04cbd651c195aa0b6bb422e3fb8b1511 Mon Sep 17 00:00:00 2001 From: hunuza Date: Sun, 21 Dec 2008 14:42:18 +0100 Subject: [PATCH 244/256] [6927] Send correct level in error message due to too low level to create arena team. Signed-off-by: hunuza --- src/game/PetitionsHandler.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/PetitionsHandler.cpp b/src/game/PetitionsHandler.cpp index ea766facd..712d8bc36 100644 --- a/src/game/PetitionsHandler.cpp +++ b/src/game/PetitionsHandler.cpp @@ -111,7 +111,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data) // TODO: find correct opcode if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { - SendNotification(LANG_ARENA_ONE_TOOLOW, 70); + SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)); return; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 101dc5fd9..fcbcb4319 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6926" + #define REVISION_NR "6927" #endif // __REVISION_NR_H__ From ed4efc317c4af79f4a584dfaaf22fdcaf465c119 Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Mon, 22 Dec 2008 01:22:09 +0200 Subject: [PATCH 245/256] [6928] Corrected the handling of evade and threat for creature summoned pets. Should fix some of the setVisibility crashes. --- src/game/MotionMaster.cpp | 11 ++++++++++- src/game/Unit.cpp | 12 ++++++++++-- src/shared/revision_nr.h | 2 +- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index 2dc42cd4d..23beef949 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -150,8 +150,17 @@ MotionMaster::MoveTargetedHome() } else if(i_owner->GetTypeId()==TYPEID_UNIT && ((Creature*)i_owner)->GetCharmerOrOwnerGUID()) { - sLog.outError("Pet or controlled creature (Entry: %u GUID: %u) attempt targeted home", + DEBUG_LOG("Pet or controlled creature (Entry: %u GUID: %u) targeting home", i_owner->GetEntry(), i_owner->GetGUIDLow() ); + Unit *target = ((Creature*)i_owner)->GetCharmerOrOwner(); + if(target) + { + i_owner->addUnitState(UNIT_STAT_FOLLOW); + DEBUG_LOG("Following %s (GUID: %u)", + target->GetTypeId()==TYPEID_PLAYER ? "player" : "creature", + target->GetTypeId()==TYPEID_PLAYER ? target->GetGUIDLow() : ((Creature*)target)->GetDBTableGUIDLow() ); + Mutate(new TargetedMovementGenerator(*target,PET_FOLLOW_DIST,PET_FOLLOW_ANGLE)); + } } else { diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 5905df7cd..d5e66c756 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -9094,8 +9094,16 @@ bool Unit::CanHaveThreatList() const if( !isAlive() ) return false; - // pets and totems can not have threat list - if( ((Creature*)this)->isPet() || ((Creature*)this)->isTotem() || ((Creature*)this)->isVehicle() ) + // totems can not have threat list + 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; return true; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index fcbcb4319..1a4a6befc 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6927" + #define REVISION_NR "6928" #endif // __REVISION_NR_H__ From bf3ffdaff6af6397e492ed70c5b2cac2ab3808f3 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 22 Dec 2008 15:25:43 +0300 Subject: [PATCH 246/256] MaNGOS 0.12 release. --- ChangeLog | 77 +++++++++++++++++++++++++++++++++++- NEWS | 9 ++++- src/shared/SystemConfig.h.in | 2 +- win/VC71/mangosd.vcproj | 4 +- win/VC71/realmd.vcproj | 4 +- win/VC80/mangosd.vcproj | 8 ++-- win/VC80/realmd.vcproj | 8 ++-- win/VC90/mangosd.vcproj | 8 ++-- win/VC90/realmd.vcproj | 4 +- 9 files changed, 102 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index db287f281..e9645b67c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ -MaNGOS 0.12 (??? ??? 2008) +MaNGOS 0.13 (??? ??? 2009) - MaNGOS 0.12 - Codename "???" - adds further improvements to the + MaNGOS 0.13 - adds further improvements to the server core as well as to the majority of game classes and the game content database. @@ -12,6 +12,79 @@ MaNGOS 0.12 (??? ??? 2008) * Fixed Bugs: ??? * Total number of changes: ??? +MaNGOS 0.12 (Dec 22 2008) + + MaNGOS 0.12 - adds further improvements to the + server core as well as to the majority of game classes and the game content + database. + + ==== Game Features ==== + + * Added: Support for different difficult instances, proper instances reset and proper group/player binding to instances. + * Added: Support for arena system. + * Added: Support for declined names (with Cyrillic client). + * Added: Support for auction pending mail and 1 hour delay in money delivery to owner. + * Added: Support for possibility reject warlock's player summon by targeted player. + * Added: Support for talent based pet auras. + * Added: Support for auto-reward quests. + * Added: Support for trap arming delay in combat state. + * Added: Support for show enchantment item effect on login screen. + * Added: Support for restoration buff in battlegrounds. + * Added: Support for dependent spell disabling (instead removing) at talent reset until talent re-learning. + * Added: Support for guild/arena team leaders delete protection. + * Added: Support for areatrigger scripting. + * Added: Support for honor rewards from quests. + * Added: Support for realmd reconnect from login character list. + * Added: Support for configurable assistance aggro delaying. + * Improved: Better duels work. + * Improved: Improvements in battleground system work including really instancing battlegrounds. + * Improved: Better support game localization for players and GMs. + * Improved: More server-side re-checks for client side primary checked data for prevent cheating. + * Improved: Player can't dodge attack from behind. + * Improved: Correctly animate eating/drinking in cases sitting at chairs/etc. + * Improved: Better guardians related functionality work. + * Improved: Expected instant logout in taxi flight at logout request. + * Improved: Re-implement raid ready check code. + * Improved: Select fishing bobber activating time in more standard way. + * Improved: Better random/waypoint creature movement work including fly case. + * Improved: Evade distance is now based on the distance from the position that the creature was at when it entered combat. + * Improved: Implemented further support for contested guards. + * Improved: Show available daily quests at map as blue marks. + * Improved: Limit distance for listen say/yell text. + * Improved: Removed dismount at login hack that now unneeded. + * Improved: Better support for low character experience gain in group with high character. + * Improved: Default behavior of pets for creatures changed to REACT_DEFENSIVE. + * Improved: Better work with combo points on miss/parry/immune. + * Improved: Allow have team dependent graveyards at entrance map for instances. + * Improved: Allowed switching INVTYPE_HOLDABLE items during combat. + * Improved: Make flying creatures fall on ground when killed. + * Improved: More correct way of calculating fall damage by using fall distance and not fall time. + * plus lots of fixes for auras, effects, spells, talents, and more. + + ==== Server Features ==== + + * Added: Support for load and use multiply DBC locales data at server. + * Added: Store in `spell_chain` additional spell dependences from another spell chain for learning possibility checks. + * Added: New chat command for reload settings from mangosd.conf file without server restart need. + * Added: Set icon for realmd/mangosd binaries at Windows build. + * Added: Start use Adaptive Communication Environment (ACE) framework v.5.6.6 in server network code. + * Added: Migrate from SVN sourceforge.net to GIT github.com repository for project sources store. + * Added: Script name indexing for creature, gameobject, item, areatrigger and instance script. + * Added: The possibility to use custom process return values. + * Improved: More DB tables loading at server startup and less unneeded DB access in server work time. + * Improved: Console support for chat like commands features. Merge chat/console command list to single. + * Improved: Implement possibility output detailed and DB error log messages from scripting code. + * Improved: Better localization support for DB scripts and scripting library. + * Improved: Referenced loot data moved to new table for better sharing like data from other loot tables. + * Improved: Prevent overwriting realmd.conf and mangosd.conf on make install at Unix/Linux. + * Improved: Update Visual Leak Detector lib to Version 1.9g (beta). + * Improved: New revisions numbering and sql updates names scheme with tools support used after switch to GIT. + * Improved: Use DBC data for creating initial character items. + + ==== Statistics ==== + * Fixed Bugs: many :) + * Total number of changes: 731 (323 in git) + MaNGOS 0.11 (Jul 22 2008) MaNGOS 0.11 - adds further improvements to the diff --git a/NEWS b/NEWS index 0cac6a689..e4a7d1174 100644 --- a/NEWS +++ b/NEWS @@ -13,8 +13,15 @@ http://getmangos.com/community/ Please submit bug reports at: http://mangos.lighthouseapp.com/ -Version 0.12 +Version 0.13 * Under discussion. + * Upgrade to client version 3.0.3 (build 9183). + +Version 0.12 + * Migrate from SVN to GIT. + * Implemented arena system. + * Start using Adaptive Communication Environment (ACE) framework v.5.6.6 in server network code. + * Update Visual Leak Detector lib to Version 1.9g (beta). * Upgrade to client version 2.4.3 (build 8606). Version 0.11 diff --git a/src/shared/SystemConfig.h.in b/src/shared/SystemConfig.h.in index f2bf66d06..9ffb9eaab 100644 --- a/src/shared/SystemConfig.h.in +++ b/src/shared/SystemConfig.h.in @@ -27,7 +27,7 @@ #ifndef _VERSION #if PLATFORM == PLATFORM_WINDOWS -# define _VERSION(REVD,REVT,REVN,REVH) "0.12.0-DEV" " (" REVD " " REVT " Revision " REVN " - " REVH ")" +# define _VERSION(REVD,REVT,REVN,REVH) "0.12.1" " (" REVD " " REVT " Revision " REVN " - " REVH ")" #else # define _VERSION(REVD,REVT,REVN,REVH) "@VERSION@" " (" REVD " " REVT " Revision " REVN " - " REVH ")" #endif diff --git a/win/VC71/mangosd.vcproj b/win/VC71/mangosd.vcproj index 94b0d73d5..282500cef 100644 --- a/win/VC71/mangosd.vcproj +++ b/win/VC71/mangosd.vcproj @@ -23,7 +23,7 @@ Name="VCCLCompilerTool" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" StringPooling="TRUE" RuntimeLibrary="2" EnableFunctionLevelLinking="TRUE" @@ -92,7 +92,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" IgnoreStandardIncludePath="FALSE" BasicRuntimeChecks="3" RuntimeLibrary="3" diff --git a/win/VC71/realmd.vcproj b/win/VC71/realmd.vcproj index 6878d62a5..038922ac2 100644 --- a/win/VC71/realmd.vcproj +++ b/win/VC71/realmd.vcproj @@ -24,7 +24,7 @@ Name="VCCLCompilerTool" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV",WIN32,NDEBUG,_CONSOLE" + PreprocessorDefinitions="VERSION="0.12.1",WIN32,NDEBUG,_CONSOLE" StringPooling="TRUE" RuntimeLibrary="2" EnableFunctionLevelLinking="TRUE" @@ -91,7 +91,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" IgnoreStandardIncludePath="FALSE" BasicRuntimeChecks="3" RuntimeLibrary="3" diff --git a/win/VC80/mangosd.vcproj b/win/VC80/mangosd.vcproj index 3d32b7be1..ff631b413 100644 --- a/win/VC80/mangosd.vcproj +++ b/win/VC80/mangosd.vcproj @@ -48,7 +48,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -150,7 +150,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -250,7 +250,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -352,7 +352,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" diff --git a/win/VC80/realmd.vcproj b/win/VC80/realmd.vcproj index 9b797b0ed..28e981530 100644 --- a/win/VC80/realmd.vcproj +++ b/win/VC80/realmd.vcproj @@ -48,7 +48,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV",WIN32,NDEBUG,_CONSOLE" + PreprocessorDefinitions="VERSION="0.12.1",WIN32,NDEBUG,_CONSOLE" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -147,7 +147,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV",WIN32,NDEBUG,_CONSOLE" + PreprocessorDefinitions="VERSION="0.12.1",WIN32,NDEBUG,_CONSOLE" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -244,7 +244,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -343,7 +343,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" diff --git a/win/VC90/mangosd.vcproj b/win/VC90/mangosd.vcproj index f6ae56d33..9d54c0b83 100644 --- a/win/VC90/mangosd.vcproj +++ b/win/VC90/mangosd.vcproj @@ -49,7 +49,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -150,7 +150,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -249,7 +249,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -351,7 +351,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" diff --git a/win/VC90/realmd.vcproj b/win/VC90/realmd.vcproj index c794b4dff..2d81c18fb 100644 --- a/win/VC90/realmd.vcproj +++ b/win/VC90/realmd.vcproj @@ -49,7 +49,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-SVN",WIN32,NDEBUG,_CONSOLE" + PreprocessorDefinitions="VERSION="0.12.1",WIN32,NDEBUG,_CONSOLE" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -147,7 +147,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.0-SVN",WIN32,NDEBUG,_CONSOLE" + PreprocessorDefinitions="VERSION="0.12.1",WIN32,NDEBUG,_CONSOLE" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" From 2a4ff3d8193235c493f44a1fb989788920cf54c6 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 22 Dec 2008 15:54:26 +0300 Subject: [PATCH 247/256] Bump for 0.13.0 development. --- configure.ac | 4 ++-- src/shared/SystemConfig.h.in | 2 +- win/VC71/mangosd.vcproj | 4 ++-- win/VC71/realmd.vcproj | 4 ++-- win/VC80/mangosd.vcproj | 8 ++++---- win/VC80/realmd.vcproj | 8 ++++---- win/VC90/mangosd.vcproj | 8 ++++---- win/VC90/realmd.vcproj | 4 ++-- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/configure.ac b/configure.ac index 387c38cd1..ec2c84de2 100644 --- a/configure.ac +++ b/configure.ac @@ -14,9 +14,9 @@ ## Prelude, basic settings for Autoconf # PACKAGE: mangos -# VERSION: 0.12.0 (trunk) +# VERSION: 0.13.0 (trunk) # BUG-REPORT-ADDRESS: mangos-devs@lists.sourceforge.net -AC_INIT( [mangos], [0.12.0], [mangos-devs@lists.sourceforge.net]) +AC_INIT( [mangos], [0.13.0], [mangos-devs@lists.sourceforge.net]) AC_CONFIG_SRCDIR([src/shared/Base.cpp]) ## Prelude, basic settings for Automake diff --git a/src/shared/SystemConfig.h.in b/src/shared/SystemConfig.h.in index 9ffb9eaab..8bc6805d9 100644 --- a/src/shared/SystemConfig.h.in +++ b/src/shared/SystemConfig.h.in @@ -27,7 +27,7 @@ #ifndef _VERSION #if PLATFORM == PLATFORM_WINDOWS -# define _VERSION(REVD,REVT,REVN,REVH) "0.12.1" " (" REVD " " REVT " Revision " REVN " - " REVH ")" +# 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 diff --git a/win/VC71/mangosd.vcproj b/win/VC71/mangosd.vcproj index 282500cef..ff7a46f5d 100644 --- a/win/VC71/mangosd.vcproj +++ b/win/VC71/mangosd.vcproj @@ -23,7 +23,7 @@ Name="VCCLCompilerTool" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" StringPooling="TRUE" RuntimeLibrary="2" EnableFunctionLevelLinking="TRUE" @@ -92,7 +92,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" IgnoreStandardIncludePath="FALSE" BasicRuntimeChecks="3" RuntimeLibrary="3" diff --git a/win/VC71/realmd.vcproj b/win/VC71/realmd.vcproj index 038922ac2..1eb41decc 100644 --- a/win/VC71/realmd.vcproj +++ b/win/VC71/realmd.vcproj @@ -24,7 +24,7 @@ Name="VCCLCompilerTool" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1",WIN32,NDEBUG,_CONSOLE" + PreprocessorDefinitions="VERSION="0.13.0-DEV",WIN32,NDEBUG,_CONSOLE" StringPooling="TRUE" RuntimeLibrary="2" EnableFunctionLevelLinking="TRUE" @@ -91,7 +91,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" IgnoreStandardIncludePath="FALSE" BasicRuntimeChecks="3" RuntimeLibrary="3" diff --git a/win/VC80/mangosd.vcproj b/win/VC80/mangosd.vcproj index ff631b413..892a33b4a 100644 --- a/win/VC80/mangosd.vcproj +++ b/win/VC80/mangosd.vcproj @@ -48,7 +48,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -150,7 +150,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -250,7 +250,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -352,7 +352,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" diff --git a/win/VC80/realmd.vcproj b/win/VC80/realmd.vcproj index 28e981530..c096efc78 100644 --- a/win/VC80/realmd.vcproj +++ b/win/VC80/realmd.vcproj @@ -48,7 +48,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1",WIN32,NDEBUG,_CONSOLE" + PreprocessorDefinitions="VERSION="0.13.0-DEV",WIN32,NDEBUG,_CONSOLE" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -147,7 +147,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1",WIN32,NDEBUG,_CONSOLE" + PreprocessorDefinitions="VERSION="0.13.0-DEV",WIN32,NDEBUG,_CONSOLE" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -244,7 +244,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -343,7 +343,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" diff --git a/win/VC90/mangosd.vcproj b/win/VC90/mangosd.vcproj index 9d54c0b83..f9a4f6682 100644 --- a/win/VC90/mangosd.vcproj +++ b/win/VC90/mangosd.vcproj @@ -49,7 +49,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -150,7 +150,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;NDEBUG;_CONSOLE;ENABLE_CLI" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -249,7 +249,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" @@ -351,7 +351,7 @@ AdditionalOptions="/MP" Optimization="0" AdditionalIncludeDirectories="..\..\dep\include,..\..\src\framework,..\..\src\shared,..\..\src\game,..\..\src\mangosd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" + PreprocessorDefinitions="VERSION="0.13.0-DEV";WIN32;_DEBUG;MANGOS_DEBUG;_CONSOLE;ENABLE_CLI" IgnoreStandardIncludePath="false" BasicRuntimeChecks="3" RuntimeLibrary="3" diff --git a/win/VC90/realmd.vcproj b/win/VC90/realmd.vcproj index 2d81c18fb..5016cd66f 100644 --- a/win/VC90/realmd.vcproj +++ b/win/VC90/realmd.vcproj @@ -49,7 +49,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1",WIN32,NDEBUG,_CONSOLE" + PreprocessorDefinitions="VERSION="0.13.0-DEV",WIN32,NDEBUG,_CONSOLE" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" @@ -147,7 +147,7 @@ AdditionalOptions="/MP" InlineFunctionExpansion="1" AdditionalIncludeDirectories="..\..\dep\include;..\..\src\framework;..\..\src\shared;..\..\src\realmd;..\..\dep\ACE_wrappers" - PreprocessorDefinitions="VERSION="0.12.1",WIN32,NDEBUG,_CONSOLE" + PreprocessorDefinitions="VERSION="0.13.0-DEV",WIN32,NDEBUG,_CONSOLE" StringPooling="true" RuntimeLibrary="2" EnableFunctionLevelLinking="true" From 353b3c7d275f2d4c6d85d6b98b3ee5c38c00a3f5 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Mon, 22 Dec 2008 16:53:30 +0300 Subject: [PATCH 248/256] Prepare sql updates for merge. This sql updates including chaarcter convertion queries: 2008_12_22_18_characters_characters.sql 2008_12_22_19_characters_item_instance.sql --- sql/characters.sql | 38 +++++++---- sql/mangos.sql | 2 +- ..._22_01_mangos_creature_equip_template.sql} | 2 + ...008_12_22_02_characters_character_pet.sql} | 2 + .../2008_12_22_03_mangos_item_template.sql} | 2 + .../2008_12_22_04_mangos_item_template.sql | 4 ++ ...2008_12_22_05_characters_account_data.sql} | 2 + ...2_06_characters_character_achievement.sql} | 8 ++- .../2008_12_22_07_mangos_quest_template.sql} | 2 + ...12_22_08_mangos_milling_loot_template.sql} | 2 + .../2008_12_22_09_mangos_spell_affect.sql} | 2 + .../2008_12_22_10_mangos_string.sql} | 2 + ...2_22_11_mangos_player_classlevelstats.sql} | 2 + ...008_12_22_12_mangos_player_levelstats.sql} | 2 + .../2008_12_22_13_mangos_item_template.sql | 4 ++ ...2008_12_22_14_mangos_playercreateinfo.sql} | 2 + ..._22_15_mangos_playercreateinfo_action.sql} | 2 + ...2_22_16_mangos_playercreateinfo_spell.sql} | 2 + .../2008_12_22_17_mangos_item_template.sql} | 2 + .../2008_12_22_18_characters_characters.sql | 68 +++++++++++++++++++ ...2008_12_22_19_characters_item_instance.sql | 15 ++++ sql/updates/Makefile.am | 38 +++++++++++ sql/wotlk_updates/13_mangos_item_template.sql | 2 - sql/wotlk_updates/4_mangos_item_template.sql | 2 - 24 files changed, 190 insertions(+), 19 deletions(-) rename sql/{wotlk_updates/1_mangos_creature_equip_template.sql => updates/2008_12_22_01_mangos_creature_equip_template.sql} (78%) rename sql/{wotlk_updates/2_character_character_pet.sql => updates/2008_12_22_02_characters_character_pet.sql} (58%) rename sql/{wotlk_updates/3_mangos_item_template.sql => updates/2008_12_22_03_mangos_item_template.sql} (77%) create mode 100644 sql/updates/2008_12_22_04_mangos_item_template.sql rename sql/{wotlk_updates/5_character_account_data.sql => updates/2008_12_22_05_characters_account_data.sql} (65%) rename sql/{wotlk_updates/6_character_achievement.sql => updates/2008_12_22_06_characters_character_achievement.sql} (53%) rename sql/{wotlk_updates/7_mangos_quest_template.sql => updates/2008_12_22_07_mangos_quest_template.sql} (61%) rename sql/{wotlk_updates/8_mangos_milling_loot_template.sql => updates/2008_12_22_08_mangos_milling_loot_template.sql} (83%) rename sql/{wotlk_updates/9_mangos_spell_affect.sql => updates/2008_12_22_09_mangos_spell_affect.sql} (77%) rename sql/{wotlk_updates/10_mangos_string.sql => updates/2008_12_22_10_mangos_string.sql} (68%) rename sql/{wotlk_updates/11_mangos_player_classlevelstats.sql => updates/2008_12_22_11_mangos_player_classlevelstats.sql} (95%) rename sql/{wotlk_updates/12_mangos_player_levelstats.sql => updates/2008_12_22_12_mangos_player_levelstats.sql} (99%) create mode 100644 sql/updates/2008_12_22_13_mangos_item_template.sql rename sql/{wotlk_updates/14_mangos_playercreateinfo.sql => updates/2008_12_22_14_mangos_playercreateinfo.sql} (79%) rename sql/{wotlk_updates/15_mangos_playercreateinfo_action.sql => updates/2008_12_22_15_mangos_playercreateinfo_action.sql} (91%) rename sql/{wotlk_updates/16_mangos_playercreateinfo_spell.sql => updates/2008_12_22_16_mangos_playercreateinfo_spell.sql} (99%) rename sql/{wotlk_updates/17_mangos_item_template.sql => updates/2008_12_22_17_mangos_item_template.sql} (97%) create mode 100644 sql/updates/2008_12_22_18_characters_characters.sql create mode 100644 sql/updates/2008_12_22_19_characters_item_instance.sql delete mode 100644 sql/wotlk_updates/13_mangos_item_template.sql delete mode 100644 sql/wotlk_updates/4_mangos_item_template.sql diff --git a/sql/characters.sql b/sql/characters.sql index d18ac6132..0dffc512e 100644 --- a/sql/characters.sql +++ b/sql/characters.sql @@ -15,22 +15,13 @@ /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - --- --- Table structure for table `saved_variables` --- - -CREATE TABLE `saved_variables` ( - `NextArenaPointDistributionTime` bigint(40) UNSIGNED NOT NULL DEFAULT '0' -) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Variable Saves'; - -- -- Table structure for table `character_db_version` -- DROP TABLE IF EXISTS `character_db_version`; CREATE TABLE `character_db_version` ( - `required_2008_12_15_01_character_arenas` bit(1) default NULL + `required_2008_12_22_19_characters_item_instance` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB'; -- @@ -253,7 +244,8 @@ UNLOCK TABLES; -- Table structure for table `character_achievement` -- -CREATE TABLE IF NOT EXISTS `character_achievement` ( +DROP TABLE IF EXISTS `character_achievement`; +CREATE TABLE `character_achievement` ( `guid` int(11) NOT NULL, `achievement` int(11) NOT NULL, `date` int(11) NOT NULL, @@ -273,7 +265,8 @@ UNLOCK TABLES; -- Table structure for table `character_achievement_progress` -- -CREATE TABLE IF NOT EXISTS `character_achievement_progress` ( +DROP TABLE IF EXISTS `character_achievement_progress`; +CREATE TABLE `character_achievement_progress` ( `guid` int(11) NOT NULL, `criteria` int(11) NOT NULL, `counter` int(11) NOT NULL, @@ -1294,6 +1287,7 @@ CREATE TABLE `petition_sign` ( `type` int(10) unsigned NOT NULL default '0', PRIMARY KEY (`petitionguid`,`playerguid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Guild System'; + -- -- Dumping data for table `petition_sign` -- @@ -1304,6 +1298,26 @@ LOCK TABLES `petition_sign` WRITE; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; +-- +-- Table structure for table `saved_variables` +-- + +DROP TABLE IF EXISTS `saved_variables`; +CREATE TABLE `saved_variables` ( + `NextArenaPointDistributionTime` bigint(40) UNSIGNED NOT NULL DEFAULT '0' +) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Variable Saves'; + +-- +-- Dumping data for table `saved_variables` +-- + +LOCK TABLES `saved_variables` WRITE; +/*!40000 ALTER TABLE `saved_variables` DISABLE KEYS */; +/*!40000 ALTER TABLE `saved_variables` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + + /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; diff --git a/sql/mangos.sql b/sql/mangos.sql index 6806c41f7..6cf7f0541 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_2008_12_15_01_mangos_arenas` bit(1) default NULL + `required_2008_12_22_17_mangos_item_template` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- diff --git a/sql/wotlk_updates/1_mangos_creature_equip_template.sql b/sql/updates/2008_12_22_01_mangos_creature_equip_template.sql similarity index 78% rename from sql/wotlk_updates/1_mangos_creature_equip_template.sql rename to sql/updates/2008_12_22_01_mangos_creature_equip_template.sql index fc64c1d9d..6efaae7ae 100644 --- a/sql/wotlk_updates/1_mangos_creature_equip_template.sql +++ b/sql/updates/2008_12_22_01_mangos_creature_equip_template.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_15_01_mangos_arenas required_2008_12_22_01_mangos_creature_equip_template bit; + TRUNCATE creature_equip_template; alter table `creature_equip_template` diff --git a/sql/wotlk_updates/2_character_character_pet.sql b/sql/updates/2008_12_22_02_characters_character_pet.sql similarity index 58% rename from sql/wotlk_updates/2_character_character_pet.sql rename to sql/updates/2008_12_22_02_characters_character_pet.sql index 98c0f6aad..b083232ae 100644 --- a/sql/wotlk_updates/2_character_character_pet.sql +++ b/sql/updates/2008_12_22_02_characters_character_pet.sql @@ -1,3 +1,5 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_15_01_character_arenas required_2008_12_22_02_characters_character_pet bit; + alter table `character_pet` drop column `trainpoint`, drop column `loyaltypoints`, diff --git a/sql/wotlk_updates/3_mangos_item_template.sql b/sql/updates/2008_12_22_03_mangos_item_template.sql similarity index 77% rename from sql/wotlk_updates/3_mangos_item_template.sql rename to sql/updates/2008_12_22_03_mangos_item_template.sql index 09de10c3e..3d27b3f3d 100644 --- a/sql/wotlk_updates/3_mangos_item_template.sql +++ b/sql/updates/2008_12_22_03_mangos_item_template.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_01_mangos_creature_equip_template required_2008_12_22_03_mangos_item_template bit; + alter table `item_template` add column `ScalingStatDistribution` smallint(6) DEFAULT '0' NOT NULL after `stat_value10`, add column `ScalingStatValue` smallint(6) DEFAULT '0' NOT NULL after `ScalingStatDistribution`, diff --git a/sql/updates/2008_12_22_04_mangos_item_template.sql b/sql/updates/2008_12_22_04_mangos_item_template.sql new file mode 100644 index 000000000..685c44a4e --- /dev/null +++ b/sql/updates/2008_12_22_04_mangos_item_template.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_03_mangos_item_template required_2008_12_22_04_mangos_item_template bit; + +alter table `item_template` + add column `StatsCount` tinyint(3) UNSIGNED DEFAULT '0' NOT NULL after `ContainerSlots`; diff --git a/sql/wotlk_updates/5_character_account_data.sql b/sql/updates/2008_12_22_05_characters_account_data.sql similarity index 65% rename from sql/wotlk_updates/5_character_account_data.sql rename to sql/updates/2008_12_22_05_characters_account_data.sql index 08b9a5b5b..5923bfe96 100644 --- a/sql/wotlk_updates/5_character_account_data.sql +++ b/sql/updates/2008_12_22_05_characters_account_data.sql @@ -1,3 +1,5 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_22_02_characters_character_pet required_2008_12_22_05_characters_account_data bit; + CREATE TABLE `account_data` ( `account` int(11) unsigned NOT NULL default '0', `type` int(11) unsigned NOT NULL default '0', diff --git a/sql/wotlk_updates/6_character_achievement.sql b/sql/updates/2008_12_22_06_characters_character_achievement.sql similarity index 53% rename from sql/wotlk_updates/6_character_achievement.sql rename to sql/updates/2008_12_22_06_characters_character_achievement.sql index 23326eb6f..ca5c240b6 100644 --- a/sql/wotlk_updates/6_character_achievement.sql +++ b/sql/updates/2008_12_22_06_characters_character_achievement.sql @@ -1,11 +1,15 @@ -CREATE TABLE IF NOT EXISTS `character_achievement` ( +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_22_05_characters_account_data required_2008_12_22_06_characters_character_achievement bit; + +DROP TABLE IF EXISTS `character_achievement`; +CREATE TABLE `character_achievement` ( `guid` int(11) NOT NULL, `achievement` int(11) NOT NULL, `date` int(11) NOT NULL, PRIMARY KEY (`guid`,`achievement`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; -CREATE TABLE IF NOT EXISTS `character_achievement_progress` ( +DROP TABLE IF EXISTS `character_achievement_progress`; +CREATE TABLE `character_achievement_progress` ( `guid` int(11) NOT NULL, `criteria` int(11) NOT NULL, `counter` int(11) NOT NULL, diff --git a/sql/wotlk_updates/7_mangos_quest_template.sql b/sql/updates/2008_12_22_07_mangos_quest_template.sql similarity index 61% rename from sql/wotlk_updates/7_mangos_quest_template.sql rename to sql/updates/2008_12_22_07_mangos_quest_template.sql index 8d387ff8b..a3795504b 100644 --- a/sql/wotlk_updates/7_mangos_quest_template.sql +++ b/sql/updates/2008_12_22_07_mangos_quest_template.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_04_mangos_item_template required_2008_12_22_07_mangos_quest_template bit; + alter table `quest_template` add column `PlayersSlain` tinyint(3) UNSIGNED DEFAULT '0' NOT NULL after `CharTitleId`, add column `BonusTalents` tinyint(3) UNSIGNED DEFAULT '0' NOT NULL after `PlayersSlain`; diff --git a/sql/wotlk_updates/8_mangos_milling_loot_template.sql b/sql/updates/2008_12_22_08_mangos_milling_loot_template.sql similarity index 83% rename from sql/wotlk_updates/8_mangos_milling_loot_template.sql rename to sql/updates/2008_12_22_08_mangos_milling_loot_template.sql index 74e7bf2de..18500508c 100644 --- a/sql/wotlk_updates/8_mangos_milling_loot_template.sql +++ b/sql/updates/2008_12_22_08_mangos_milling_loot_template.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_07_mangos_quest_template required_2008_12_22_08_mangos_milling_loot_template bit; + DROP TABLE IF EXISTS `milling_loot_template`; CREATE TABLE `milling_loot_template` ( `entry` mediumint(8) unsigned NOT NULL default '0', diff --git a/sql/wotlk_updates/9_mangos_spell_affect.sql b/sql/updates/2008_12_22_09_mangos_spell_affect.sql similarity index 77% rename from sql/wotlk_updates/9_mangos_spell_affect.sql rename to sql/updates/2008_12_22_09_mangos_spell_affect.sql index 20b9e987b..6d5635ece 100644 --- a/sql/wotlk_updates/9_mangos_spell_affect.sql +++ b/sql/updates/2008_12_22_09_mangos_spell_affect.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_08_mangos_milling_loot_template required_2008_12_22_09_mangos_spell_affect bit; + -- -- Table structure for table `spell_affect` -- diff --git a/sql/wotlk_updates/10_mangos_string.sql b/sql/updates/2008_12_22_10_mangos_string.sql similarity index 68% rename from sql/wotlk_updates/10_mangos_string.sql rename to sql/updates/2008_12_22_10_mangos_string.sql index 7ac51e307..16c9f0dda 100644 --- a/sql/wotlk_updates/10_mangos_string.sql +++ b/sql/updates/2008_12_22_10_mangos_string.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_09_mangos_spell_affect required_2008_12_22_10_mangos_string bit; + INSERT INTO `mangos_string` VALUES (345,'Forced customize for player %s will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), (346,'Forced customize for player %s (GUID #%u) will be requested at next login.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); diff --git a/sql/wotlk_updates/11_mangos_player_classlevelstats.sql b/sql/updates/2008_12_22_11_mangos_player_classlevelstats.sql similarity index 95% rename from sql/wotlk_updates/11_mangos_player_classlevelstats.sql rename to sql/updates/2008_12_22_11_mangos_player_classlevelstats.sql index 6133ac0a0..70c947f97 100644 --- a/sql/wotlk_updates/11_mangos_player_classlevelstats.sql +++ b/sql/updates/2008_12_22_11_mangos_player_classlevelstats.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_10_mangos_string required_2008_12_22_11_mangos_player_classlevelstats bit; + DELETE FROM `player_classlevelstats` WHERE class = 6 OR level > 70; INSERT INTO `player_classlevelstats` VALUES (1,71,4720,0), diff --git a/sql/wotlk_updates/12_mangos_player_levelstats.sql b/sql/updates/2008_12_22_12_mangos_player_levelstats.sql similarity index 99% rename from sql/wotlk_updates/12_mangos_player_levelstats.sql rename to sql/updates/2008_12_22_12_mangos_player_levelstats.sql index 4d8885c83..f74733407 100644 --- a/sql/wotlk_updates/12_mangos_player_levelstats.sql +++ b/sql/updates/2008_12_22_12_mangos_player_levelstats.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_11_mangos_player_classlevelstats required_2008_12_22_12_mangos_player_levelstats bit; + DELETE FROM `player_levelstats`; INSERT INTO `player_levelstats` VALUES (1,1,1,23,20,22,20,20), diff --git a/sql/updates/2008_12_22_13_mangos_item_template.sql b/sql/updates/2008_12_22_13_mangos_item_template.sql new file mode 100644 index 000000000..6b2d64f51 --- /dev/null +++ b/sql/updates/2008_12_22_13_mangos_item_template.sql @@ -0,0 +1,4 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_12_mangos_player_levelstats required_2008_12_22_13_mangos_item_template bit; + +ALTER TABLE `item_template` + CHANGE COLUMN `TotemCategory` `TotemCategory` mediumint(9) NOT NULL default '0'; diff --git a/sql/wotlk_updates/14_mangos_playercreateinfo.sql b/sql/updates/2008_12_22_14_mangos_playercreateinfo.sql similarity index 79% rename from sql/wotlk_updates/14_mangos_playercreateinfo.sql rename to sql/updates/2008_12_22_14_mangos_playercreateinfo.sql index 0279a3311..f36d79652 100644 --- a/sql/wotlk_updates/14_mangos_playercreateinfo.sql +++ b/sql/updates/2008_12_22_14_mangos_playercreateinfo.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_13_mangos_item_template required_2008_12_22_14_mangos_playercreateinfo bit; + DELETE FROM `playercreateinfo` WHERE class = 6; INSERT INTO `playercreateinfo` VALUES (1 ,6,609,4298,2355.84,-5664.77,426.028), diff --git a/sql/wotlk_updates/15_mangos_playercreateinfo_action.sql b/sql/updates/2008_12_22_15_mangos_playercreateinfo_action.sql similarity index 91% rename from sql/wotlk_updates/15_mangos_playercreateinfo_action.sql rename to sql/updates/2008_12_22_15_mangos_playercreateinfo_action.sql index c2b2e1045..54bcde291 100644 --- a/sql/wotlk_updates/15_mangos_playercreateinfo_action.sql +++ b/sql/updates/2008_12_22_15_mangos_playercreateinfo_action.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_14_mangos_playercreateinfo required_2008_12_22_15_mangos_playercreateinfo_action bit; + DELETE FROM playercreateinfo_action WHERE class = 6; INSERT INTO playercreateinfo_action VALUES (1,6,0,6603,0,0), diff --git a/sql/wotlk_updates/16_mangos_playercreateinfo_spell.sql b/sql/updates/2008_12_22_16_mangos_playercreateinfo_spell.sql similarity index 99% rename from sql/wotlk_updates/16_mangos_playercreateinfo_spell.sql rename to sql/updates/2008_12_22_16_mangos_playercreateinfo_spell.sql index a36e8215d..664ea0291 100644 --- a/sql/wotlk_updates/16_mangos_playercreateinfo_spell.sql +++ b/sql/updates/2008_12_22_16_mangos_playercreateinfo_spell.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_15_mangos_playercreateinfo_action required_2008_12_22_16_mangos_playercreateinfo_spell bit; + DELETE FROM `playercreateinfo_spell` WHERE `class` = 6; INSERT INTO `playercreateinfo_spell` VALUES (1,6,81,'Dodge',1), diff --git a/sql/wotlk_updates/17_mangos_item_template.sql b/sql/updates/2008_12_22_17_mangos_item_template.sql similarity index 97% rename from sql/wotlk_updates/17_mangos_item_template.sql rename to sql/updates/2008_12_22_17_mangos_item_template.sql index 3a46cba3e..9e2eafaf7 100644 --- a/sql/wotlk_updates/17_mangos_item_template.sql +++ b/sql/updates/2008_12_22_17_mangos_item_template.sql @@ -1,3 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_2008_12_22_16_mangos_playercreateinfo_spell required_2008_12_22_17_mangos_item_template bit; + DELETE FROM item_template WHERE entry IN (34648,34649,34650,34651,34652,34653,34655,34656,34657,34658,34659,38145,38147,41751); INSERT INTO item_template VALUES (34648,4,4,-1,'Acherus Knight\'s Greaves',51496,2,32768,1,51,10,8,-1,-1,60,55,0,0,0,0,0,0,0,0,1,0,3,4,10,7,12,3,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,392,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,0,0,0,0,-1,0,-1,1,'',0,0,0,0,0,6,0,0,0,0,0,55,0,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,'',0,0,0,0), diff --git a/sql/updates/2008_12_22_18_characters_characters.sql b/sql/updates/2008_12_22_18_characters_characters.sql new file mode 100644 index 000000000..21f25913a --- /dev/null +++ b/sql/updates/2008_12_22_18_characters_characters.sql @@ -0,0 +1,68 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_22_06_characters_character_achievement required_2008_12_22_18_characters_characters bit; + +UPDATE characters SET data = REPLACE(data,' ',' '); +UPDATE characters SET data = CONCAT(TRIM(data),' '); + + +UPDATE characters SET data = CONCAT( + SUBSTRING(data, 1, length(SUBSTRING_INDEX(data, ' ', 10))), " 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 10))+2, length(SUBSTRING_INDEX(data, ' ', 18))- length(SUBSTRING_INDEX(data, ' ', 10)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 20))+2, length(SUBSTRING_INDEX(data, ' ', 22))- length(SUBSTRING_INDEX(data, ' ', 20)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 36))+2, length(SUBSTRING_INDEX(data, ' ', 37))- length(SUBSTRING_INDEX(data, ' ', 36)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 22))+2, length(SUBSTRING_INDEX(data, ' ', 28))- length(SUBSTRING_INDEX(data, ' ', 22)) - 1), " 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 28))+2, length(SUBSTRING_INDEX(data, ' ', 34))- length(SUBSTRING_INDEX(data, ' ', 28)) - 1), " 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1564))+2, length(SUBSTRING_INDEX(data, ' ', 1565))- length(SUBSTRING_INDEX(data, ' ', 1564)) - 1), " 0 0 0 0 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1565))+2, length(SUBSTRING_INDEX(data, ' ', 1566))- length(SUBSTRING_INDEX(data, ' ', 1565)) - 1), " 0 0 0 0 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 34))+2, length(SUBSTRING_INDEX(data, ' ', 36))- length(SUBSTRING_INDEX(data, ' ', 34)) - 1), " 0 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 46))+2, length(SUBSTRING_INDEX(data, ' ', 48))- length(SUBSTRING_INDEX(data, ' ', 46)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 146))+2, length(SUBSTRING_INDEX(data, ' ', 170))- length(SUBSTRING_INDEX(data, ' ', 146)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 171))+2, length(SUBSTRING_INDEX(data, ' ', 209))- length(SUBSTRING_INDEX(data, ' ', 171)) - 1), " ", + ((SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 209))+2, length(SUBSTRING_INDEX(data, ' ', 210))- length(SUBSTRING_INDEX(data, ' ', 209)) - 1) & ~0x100) | ((SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 46))+2, length(SUBSTRING_INDEX(data, ' ', 47))- length(SUBSTRING_INDEX(data, ' ', 46)) - 1) & 0x1000) >> 4)), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 210))+2, length(SUBSTRING_INDEX(data, ' ', 233))- length(SUBSTRING_INDEX(data, ' ', 210)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 233))+2, length(SUBSTRING_INDEX(data, ' ', 358))- length(SUBSTRING_INDEX(data, ' ', 233)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 358))+2, length(SUBSTRING_INDEX(data, ' ', 359))- length(SUBSTRING_INDEX(data, ' ', 358)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 359))+2, length(SUBSTRING_INDEX(data, ' ', 374))- length(SUBSTRING_INDEX(data, ' ', 359)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 374))+2, length(SUBSTRING_INDEX(data, ' ', 375))- length(SUBSTRING_INDEX(data, ' ', 374)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 375))+2, length(SUBSTRING_INDEX(data, ' ', 390))- length(SUBSTRING_INDEX(data, ' ', 375)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 390))+2, length(SUBSTRING_INDEX(data, ' ', 391))- length(SUBSTRING_INDEX(data, ' ', 390)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 391))+2, length(SUBSTRING_INDEX(data, ' ', 406))- length(SUBSTRING_INDEX(data, ' ', 391)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 406))+2, length(SUBSTRING_INDEX(data, ' ', 407))- length(SUBSTRING_INDEX(data, ' ', 406)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 407))+2, length(SUBSTRING_INDEX(data, ' ', 422))- length(SUBSTRING_INDEX(data, ' ', 407)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 422))+2, length(SUBSTRING_INDEX(data, ' ', 423))- length(SUBSTRING_INDEX(data, ' ', 422)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 423))+2, length(SUBSTRING_INDEX(data, ' ', 438))- length(SUBSTRING_INDEX(data, ' ', 423)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 438))+2, length(SUBSTRING_INDEX(data, ' ', 439))- length(SUBSTRING_INDEX(data, ' ', 438)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 439))+2, length(SUBSTRING_INDEX(data, ' ', 454))- length(SUBSTRING_INDEX(data, ' ', 439)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 454))+2, length(SUBSTRING_INDEX(data, ' ', 455))- length(SUBSTRING_INDEX(data, ' ', 454)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 455))+2, length(SUBSTRING_INDEX(data, ' ', 470))- length(SUBSTRING_INDEX(data, ' ', 455)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 470))+2, length(SUBSTRING_INDEX(data, ' ', 471))- length(SUBSTRING_INDEX(data, ' ', 470)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 471))+2, length(SUBSTRING_INDEX(data, ' ', 486))- length(SUBSTRING_INDEX(data, ' ', 471)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 486))+2, length(SUBSTRING_INDEX(data, ' ', 487))- length(SUBSTRING_INDEX(data, ' ', 486)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 487))+2, length(SUBSTRING_INDEX(data, ' ', 502))- length(SUBSTRING_INDEX(data, ' ', 487)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 502))+2, length(SUBSTRING_INDEX(data, ' ', 503))- length(SUBSTRING_INDEX(data, ' ', 502)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 503))+2, length(SUBSTRING_INDEX(data, ' ', 518))- length(SUBSTRING_INDEX(data, ' ', 503)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 518))+2, length(SUBSTRING_INDEX(data, ' ', 519))- length(SUBSTRING_INDEX(data, ' ', 518)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 519))+2, length(SUBSTRING_INDEX(data, ' ', 534))- length(SUBSTRING_INDEX(data, ' ', 519)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 534))+2, length(SUBSTRING_INDEX(data, ' ', 535))- length(SUBSTRING_INDEX(data, ' ', 534)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 535))+2, length(SUBSTRING_INDEX(data, ' ', 550))- length(SUBSTRING_INDEX(data, ' ', 535)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 550))+2, length(SUBSTRING_INDEX(data, ' ', 551))- length(SUBSTRING_INDEX(data, ' ', 550)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 551))+2, length(SUBSTRING_INDEX(data, ' ', 566))- length(SUBSTRING_INDEX(data, ' ', 551)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 566))+2, length(SUBSTRING_INDEX(data, ' ', 567))- length(SUBSTRING_INDEX(data, ' ', 566)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 567))+2, length(SUBSTRING_INDEX(data, ' ', 582))- length(SUBSTRING_INDEX(data, ' ', 567)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 582))+2, length(SUBSTRING_INDEX(data, ' ', 583))- length(SUBSTRING_INDEX(data, ' ', 582)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 583))+2, length(SUBSTRING_INDEX(data, ' ', 598))- length(SUBSTRING_INDEX(data, ' ', 583)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 598))+2, length(SUBSTRING_INDEX(data, ' ', 599))- length(SUBSTRING_INDEX(data, ' ', 598)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 599))+2, length(SUBSTRING_INDEX(data, ' ', 614))- length(SUBSTRING_INDEX(data, ' ', 599)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 614))+2, length(SUBSTRING_INDEX(data, ' ', 615))- length(SUBSTRING_INDEX(data, ' ', 614)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 615))+2, length(SUBSTRING_INDEX(data, ' ', 630))- length(SUBSTRING_INDEX(data, ' ', 615)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 630))+2, length(SUBSTRING_INDEX(data, ' ', 631))- length(SUBSTRING_INDEX(data, ' ', 630)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 631))+2, length(SUBSTRING_INDEX(data, ' ', 646))- length(SUBSTRING_INDEX(data, ' ', 631)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 646))+2, length(SUBSTRING_INDEX(data, ' ', 647))- length(SUBSTRING_INDEX(data, ' ', 646)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 647))+2, length(SUBSTRING_INDEX(data, ' ', 922))- length(SUBSTRING_INDEX(data, ' ', 647)) - 1), + " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 922))+2, length(SUBSTRING_INDEX(data, ' ', 926))- length(SUBSTRING_INDEX(data, ' ', 922)) - 1), " 0 0 0 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 926))+2, length(SUBSTRING_INDEX(data, ' ', 1332))- length(SUBSTRING_INDEX(data, ' ', 926)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1332))+2, length(SUBSTRING_INDEX(data, ' ', 1544))- length(SUBSTRING_INDEX(data, ' ', 1332)) - 1), " 0 ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1544))+2, length(SUBSTRING_INDEX(data, ' ', 1564))- length(SUBSTRING_INDEX(data, ' ', 1544)) - 1), " ", + SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 1566))+2, length(SUBSTRING_INDEX(data, ' ', 1592))- length(SUBSTRING_INDEX(data, ' ', 1566)) - 1), + " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ") +WHERE length(SUBSTRING_INDEX(data, ' ', 1592)) < length(data) and length(SUBSTRING_INDEX(data, ' ', 1593)) >= length(data); \ No newline at end of file diff --git a/sql/updates/2008_12_22_19_characters_item_instance.sql b/sql/updates/2008_12_22_19_characters_item_instance.sql new file mode 100644 index 000000000..96f31ff47 --- /dev/null +++ b/sql/updates/2008_12_22_19_characters_item_instance.sql @@ -0,0 +1,15 @@ +ALTER TABLE character_db_version CHANGE COLUMN required_2008_12_22_18_characters_characters required_2008_12_22_19_characters_item_instance bit; + +UPDATE item_instance SET data = REPLACE(data,' ',' '); +UPDATE item_instance SET data = CONCAT(TRIM(data),' '); + +UPDATE item_instance SET data= CONCAT( + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',30),' ',-30),' 0 0 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',60),' ',-60+30),' 0 ') +WHERE SUBSTRING_INDEX(data,' ',60) = data AND SUBSTRING_INDEX(data,' ',60-1) <> data; + +UPDATE item_instance SET data= CONCAT( + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',30),' ',-30),' 0 0 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',60),' ',-60+30),' 0 ', + SUBSTRING_INDEX(SUBSTRING_INDEX(data,' ',134),' ',-134+60)) +WHERE SUBSTRING_INDEX(data,' ',134) = data AND SUBSTRING_INDEX(data,' ',134-1) <> data; diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 6cebe667c..33d0db725 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -143,6 +143,25 @@ pkgdata_DATA = \ 2008_12_03_01_character_guild_member.sql \ 2008_12_15_01_character_arenas.sql \ 2008_12_15_01_mangos_arenas.sql \ + 2008_12_22_01_mangos_creature_equip_template.sql \ + 2008_12_22_02_characters_character_pet.sql \ + 2008_12_22_03_mangos_item_template.sql \ + 2008_12_22_04_mangos_item_template.sql \ + 2008_12_22_05_characters_account_data.sql \ + 2008_12_22_06_characters_character_achievement.sql \ + 2008_12_22_07_mangos_quest_template.sql \ + 2008_12_22_08_mangos_milling_loot_template.sql \ + 2008_12_22_09_mangos_spell_affect.sql \ + 2008_12_22_10_mangos_string.sql \ + 2008_12_22_11_mangos_player_classlevelstats.sql \ + 2008_12_22_12_mangos_player_levelstats.sql \ + 2008_12_22_13_mangos_item_template.sql \ + 2008_12_22_14_mangos_playercreateinfo.sql \ + 2008_12_22_15_mangos_playercreateinfo_action.sql \ + 2008_12_22_16_mangos_playercreateinfo_spell.sql \ + 2008_12_22_17_mangos_item_template.sql \ + 2008_12_22_18_characters_characters.sql \ + 2008_12_22_19_characters_item_instance.sql \ README ## Additional files to include when running 'make dist' @@ -267,4 +286,23 @@ EXTRA_DIST = \ 2008_12_03_01_character_guild_member.sql \ 2008_12_15_01_character_arenas.sql \ 2008_12_15_01_mangos_arenas.sql \ + 2008_12_22_01_mangos_creature_equip_template.sql \ + 2008_12_22_02_characters_character_pet.sql \ + 2008_12_22_03_mangos_item_template.sql \ + 2008_12_22_04_mangos_item_template.sql \ + 2008_12_22_05_characters_account_data.sql \ + 2008_12_22_06_characters_character_achievement.sql \ + 2008_12_22_07_mangos_quest_template.sql \ + 2008_12_22_08_mangos_milling_loot_template.sql \ + 2008_12_22_09_mangos_spell_affect.sql \ + 2008_12_22_10_mangos_string.sql \ + 2008_12_22_11_mangos_player_classlevelstats.sql \ + 2008_12_22_12_mangos_player_levelstats.sql \ + 2008_12_22_13_mangos_item_template.sql \ + 2008_12_22_14_mangos_playercreateinfo.sql \ + 2008_12_22_15_mangos_playercreateinfo_action.sql \ + 2008_12_22_16_mangos_playercreateinfo_spell.sql \ + 2008_12_22_17_mangos_item_template.sql \ + 2008_12_22_18_characters_characters.sql \ + 2008_12_22_19_characters_item_instance.sql \ README diff --git a/sql/wotlk_updates/13_mangos_item_template.sql b/sql/wotlk_updates/13_mangos_item_template.sql deleted file mode 100644 index ae4b7ed07..000000000 --- a/sql/wotlk_updates/13_mangos_item_template.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE `item_template` - CHANGE COLUMN `TotemCategory` `TotemCategory` mediumint(9) NOT NULL default '0'; diff --git a/sql/wotlk_updates/4_mangos_item_template.sql b/sql/wotlk_updates/4_mangos_item_template.sql deleted file mode 100644 index 3f6c53b67..000000000 --- a/sql/wotlk_updates/4_mangos_item_template.sql +++ /dev/null @@ -1,2 +0,0 @@ -alter table `item_template` - add column `StatsCount` tinyint(3) UNSIGNED DEFAULT '0' NOT NULL after `ContainerSlots`; From 5eddba260e9c3b64ad79b0923ce14f7f6b959c44 Mon Sep 17 00:00:00 2001 From: tomrus88 Date: Mon, 22 Dec 2008 17:06:17 +0300 Subject: [PATCH 249/256] Fixed allowed client builds --- src/realmd/AuthCodes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/realmd/AuthCodes.h b/src/realmd/AuthCodes.h index fee37dfb8..68e10b25c 100644 --- a/src/realmd/AuthCodes.h +++ b/src/realmd/AuthCodes.h @@ -66,8 +66,8 @@ enum LoginResult // 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 and WoW:TBC 3.0.3 client build 9155, 9174, 9183, 9386... +// will only support WoW, WoW:TBC and WoW:WotLK 3.0.3 client build 9183... -#define EXPECTED_MANGOS_CLIENT_BUILD {9155, 9174, 9183, 9386, 0} +#define EXPECTED_MANGOS_CLIENT_BUILD {9183, 0} #endif From cd6717316e38955e54e49d54e07749da5912369b Mon Sep 17 00:00:00 2001 From: DiSlord Date: Tue, 23 Dec 2008 01:37:33 +0300 Subject: [PATCH 250/256] [6929] Apply new formula (from 3.0.3) for block value calculation Signed-off-by: DiSlord --- src/game/Player.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index baf042fad..76716b079 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -4355,7 +4355,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; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1a4a6befc..4c636a864 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6928" + #define REVISION_NR "6929" #endif // __REVISION_NR_H__ From a0edf095d9acc04d9135ffe0f0f94e95b285fdbb Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Tue, 23 Dec 2008 00:36:19 +0200 Subject: [PATCH 251/256] Allow arena/battleground maps to be valid without an entry in the instance template --- src/game/MapManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp index 3c89d20e9..03f080dd9 100644 --- a/src/game/MapManager.cpp +++ b/src/game/MapManager.cpp @@ -279,7 +279,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) From 03c71517ecaeac3810ae8343f736b351b02da199 Mon Sep 17 00:00:00 2001 From: DasBlub Date: Mon, 22 Dec 2008 23:05:56 +0100 Subject: [PATCH 252/256] prevent crashes in Player::_LoadArenaTeamInfo() (cherry picked from commit 9f908e877d054ff9ab973082d631bb7199f292f6) Signed-off-by: Wyk3d --- src/game/Player.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 76716b079..e12a1619d 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -13748,6 +13748,10 @@ void Player::_LoadArenaTeamInfo(QueryResult *result) uint32 personal_rating = fields[3].GetUInt32(); ArenaTeam* aTeam = objmgr.GetArenaTeamById(arenateamid); + if(!aTeam) { + sLog.outError("FATAL: couldn't load arenateam %u", arenateamid); + continue; + } uint8 arenaSlot = aTeam->GetSlot(); m_uint32Values[PLAYER_FIELD_ARENA_TEAM_INFO_1_1 + arenaSlot * 6] = arenateamid; // TeamID From f4ce2f6e9d457a3566020bed07156bc68bcd3695 Mon Sep 17 00:00:00 2001 From: Wyk3d Date: Tue, 23 Dec 2008 00:53:17 +0200 Subject: [PATCH 253/256] [6930] Added more error output on ArenaTeam load errors. --- src/game/Player.cpp | 5 +++-- src/shared/revision_nr.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e12a1619d..0b1a5b8f2 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -13748,8 +13748,9 @@ void Player::_LoadArenaTeamInfo(QueryResult *result) uint32 personal_rating = fields[3].GetUInt32(); ArenaTeam* aTeam = objmgr.GetArenaTeamById(arenateamid); - if(!aTeam) { - sLog.outError("FATAL: couldn't load arenateam %u", arenateamid); + if(!aTeam) + { + 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(); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 4c636a864..c21cd94df 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6929" + #define REVISION_NR "6930" #endif // __REVISION_NR_H__ From 9024f5274f1797389f66534bb7891cf45dcb5fdd Mon Sep 17 00:00:00 2001 From: DiSlord Date: Tue, 23 Dec 2008 02:03:47 +0300 Subject: [PATCH 254/256] [6931] Small fix (from 3.0.3) PET_BONUS_RAP_TO_SPELLDMG for Hunter pet Signed-off-by: DiSlord --- src/game/StatSystem.cpp | 2 +- src/shared/revision_nr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index e3b67e6d1..a4127e832 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -917,7 +917,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) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index c21cd94df..e2d3ae451 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6930" + #define REVISION_NR "6931" #endif // __REVISION_NR_H__ From 7cc95eefb22f124c8f3522342fa9098afc5e7f18 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Tue, 23 Dec 2008 02:03:14 +0300 Subject: [PATCH 255/256] [6932] Move some old sql updates to subdir. --- .../06360_characters_characters.sql | 0 .../{ => 0.12}/06360_characters_corpse.sql | 0 sql/updates/{ => 0.12}/06362_characters.sql | 0 .../06362_mangos_instance_template.sql | 0 .../06367_mangos_spell_proc_event.sql | 0 .../{ => 0.12}/06369_mangos_spell_affect.sql | 0 .../{ => 0.12}/06370_mangos_spell_affect.sql | 0 .../{ => 0.12}/06381_mangos_command.sql | 0 .../06387_characters_character_ticket.sql | 0 .../{ => 0.12}/06387_mangos_mangos_string.sql | 0 .../06397_mangos_creature_template.sql | 0 .../06398_mangos_creature_template.sql | 0 .../06412_characters_declinedname.sql | 0 .../{ => 0.12}/06426_mangos_locales.sql | 0 .../{ => 0.12}/06426_realmd_localization.sql | 0 .../{ => 0.12}/06431_mangos_mangos_string.sql | 0 .../{ => 0.12}/06439_mangos_command.sql | 0 .../{ => 0.12}/06456_mangos_command.sql | 0 .../{ => 0.12}/06472_realmd_account.sql | 0 .../{ => 0.12}/06492_mangos_spell_chain.sql | 0 .../06496_mangos_spell_pet_auras.sql | 0 .../06506_mangos_spell_proc_event.sql | 0 .../{ => 0.12}/06509_mangos_command.sql | 0 .../{ => 0.12}/06509_mangos_mangos_string.sql | 0 .../{ => 0.12}/06513_mangos_command.sql | 0 .../06515_mangos_spell_proc_event.sql | 0 .../06521_mangos_spell_proc_event.sql | 0 .../06523_mangos_spell_proc_event.sql | 0 .../{ => 0.12}/06528_mangos_spell_affect.sql | 0 .../06528_mangos_spell_proc_event.sql | 0 .../06538_mangos_spell_proc_event.sql | 0 .../06540_mangos_spell_proc_event.sql | 0 .../06544_mangos_spell_proc_event.sql | 0 .../{ => 0.12}/06545_mangos_command.sql | 0 .../{ => 0.12}/06557_mangos_command.sql | 0 .../06574_mangos_spell_proc_event.sql | 0 .../{ => 0.12}/06585_mangos_command.sql | 0 .../06588_mangos_spell_proc_event.sql | 0 .../06596_characters_arena_team.sql | 0 .../{ => 0.12}/06598_character_spell.sql | 0 .../{ => 0.12}/06609_mangos_mangos_string.sql | 0 .../{ => 0.12}/06613_mangos_mangos_string.sql | 0 .../06627_mangos_creature_movement.sql | 0 .../06640_mangos_reference_loot_template.sql | 0 .../06642_characters_declinedname.sql | 0 .../06668_mangos_spell_proc_event.sql | 0 .../06673_mangos_areatrigger_scripts.sql | 0 .../06676_mangos_spell_proc_event.sql | 0 .../{ => 0.12}/06681_mangos_mangos_string.sql | 0 .../06691_mangos_spell_proc_event.sql | 0 .../{ => 0.12}/06693_mangos_spell_affect.sql | 0 .../06693_mangos_spell_proc_event.sql | 0 .../06698_characters_character_tutorial.sql | 0 .../{ => 0.12}/06701_mangos_command.sql | 0 .../{ => 0.12}/06701_mangos_mangos_string.sql | 0 .../{ => 0.12}/06708_mangos_mangos_string.sql | 0 .../{ => 0.12}/06715_mangos_spell_affect.sql | 0 .../06728_mangos_quest_template.sql | 0 .../{ => 0.12}/06730_mangos_mangos_string.sql | 0 .../06740_characters_characters.sql | 0 .../{ => 0.12}/06740_mangos_command.sql | 0 .../{ => 0.12}/06740_mangos_mangos_string.sql | 0 .../{ => 0.12}/06742_mangos_command.sql | 0 .../{ => 0.12}/06742_mangos_mangos_string.sql | 0 .../{ => 0.12}/06748_mangos_mangos_string.sql | 0 .../{ => 0.12}/06750_mangos_command.sql | 0 .../{ => 0.12}/06751_realmd_account.sql | 0 .../06760_mangos_creature_template.sql | 0 sql/updates/Makefile.am | 135 ------------------ src/shared/revision_nr.h | 2 +- 70 files changed, 1 insertion(+), 136 deletions(-) rename sql/updates/{ => 0.12}/06360_characters_characters.sql (100%) rename sql/updates/{ => 0.12}/06360_characters_corpse.sql (100%) rename sql/updates/{ => 0.12}/06362_characters.sql (100%) rename sql/updates/{ => 0.12}/06362_mangos_instance_template.sql (100%) rename sql/updates/{ => 0.12}/06367_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06369_mangos_spell_affect.sql (100%) rename sql/updates/{ => 0.12}/06370_mangos_spell_affect.sql (100%) rename sql/updates/{ => 0.12}/06381_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06387_characters_character_ticket.sql (100%) rename sql/updates/{ => 0.12}/06387_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06397_mangos_creature_template.sql (100%) rename sql/updates/{ => 0.12}/06398_mangos_creature_template.sql (100%) rename sql/updates/{ => 0.12}/06412_characters_declinedname.sql (100%) rename sql/updates/{ => 0.12}/06426_mangos_locales.sql (100%) rename sql/updates/{ => 0.12}/06426_realmd_localization.sql (100%) rename sql/updates/{ => 0.12}/06431_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06439_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06456_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06472_realmd_account.sql (100%) rename sql/updates/{ => 0.12}/06492_mangos_spell_chain.sql (100%) rename sql/updates/{ => 0.12}/06496_mangos_spell_pet_auras.sql (100%) rename sql/updates/{ => 0.12}/06506_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06509_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06509_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06513_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06515_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06521_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06523_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06528_mangos_spell_affect.sql (100%) rename sql/updates/{ => 0.12}/06528_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06538_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06540_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06544_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06545_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06557_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06574_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06585_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06588_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06596_characters_arena_team.sql (100%) rename sql/updates/{ => 0.12}/06598_character_spell.sql (100%) rename sql/updates/{ => 0.12}/06609_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06613_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06627_mangos_creature_movement.sql (100%) rename sql/updates/{ => 0.12}/06640_mangos_reference_loot_template.sql (100%) rename sql/updates/{ => 0.12}/06642_characters_declinedname.sql (100%) rename sql/updates/{ => 0.12}/06668_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06673_mangos_areatrigger_scripts.sql (100%) rename sql/updates/{ => 0.12}/06676_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06681_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06691_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06693_mangos_spell_affect.sql (100%) rename sql/updates/{ => 0.12}/06693_mangos_spell_proc_event.sql (100%) rename sql/updates/{ => 0.12}/06698_characters_character_tutorial.sql (100%) rename sql/updates/{ => 0.12}/06701_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06701_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06708_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06715_mangos_spell_affect.sql (100%) rename sql/updates/{ => 0.12}/06728_mangos_quest_template.sql (100%) rename sql/updates/{ => 0.12}/06730_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06740_characters_characters.sql (100%) rename sql/updates/{ => 0.12}/06740_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06740_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06742_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06742_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06748_mangos_mangos_string.sql (100%) rename sql/updates/{ => 0.12}/06750_mangos_command.sql (100%) rename sql/updates/{ => 0.12}/06751_realmd_account.sql (100%) rename sql/updates/{ => 0.12}/06760_mangos_creature_template.sql (100%) diff --git a/sql/updates/06360_characters_characters.sql b/sql/updates/0.12/06360_characters_characters.sql similarity index 100% rename from sql/updates/06360_characters_characters.sql rename to sql/updates/0.12/06360_characters_characters.sql diff --git a/sql/updates/06360_characters_corpse.sql b/sql/updates/0.12/06360_characters_corpse.sql similarity index 100% rename from sql/updates/06360_characters_corpse.sql rename to sql/updates/0.12/06360_characters_corpse.sql diff --git a/sql/updates/06362_characters.sql b/sql/updates/0.12/06362_characters.sql similarity index 100% rename from sql/updates/06362_characters.sql rename to sql/updates/0.12/06362_characters.sql diff --git a/sql/updates/06362_mangos_instance_template.sql b/sql/updates/0.12/06362_mangos_instance_template.sql similarity index 100% rename from sql/updates/06362_mangos_instance_template.sql rename to sql/updates/0.12/06362_mangos_instance_template.sql diff --git a/sql/updates/06367_mangos_spell_proc_event.sql b/sql/updates/0.12/06367_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06367_mangos_spell_proc_event.sql rename to sql/updates/0.12/06367_mangos_spell_proc_event.sql diff --git a/sql/updates/06369_mangos_spell_affect.sql b/sql/updates/0.12/06369_mangos_spell_affect.sql similarity index 100% rename from sql/updates/06369_mangos_spell_affect.sql rename to sql/updates/0.12/06369_mangos_spell_affect.sql diff --git a/sql/updates/06370_mangos_spell_affect.sql b/sql/updates/0.12/06370_mangos_spell_affect.sql similarity index 100% rename from sql/updates/06370_mangos_spell_affect.sql rename to sql/updates/0.12/06370_mangos_spell_affect.sql diff --git a/sql/updates/06381_mangos_command.sql b/sql/updates/0.12/06381_mangos_command.sql similarity index 100% rename from sql/updates/06381_mangos_command.sql rename to sql/updates/0.12/06381_mangos_command.sql diff --git a/sql/updates/06387_characters_character_ticket.sql b/sql/updates/0.12/06387_characters_character_ticket.sql similarity index 100% rename from sql/updates/06387_characters_character_ticket.sql rename to sql/updates/0.12/06387_characters_character_ticket.sql diff --git a/sql/updates/06387_mangos_mangos_string.sql b/sql/updates/0.12/06387_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06387_mangos_mangos_string.sql rename to sql/updates/0.12/06387_mangos_mangos_string.sql diff --git a/sql/updates/06397_mangos_creature_template.sql b/sql/updates/0.12/06397_mangos_creature_template.sql similarity index 100% rename from sql/updates/06397_mangos_creature_template.sql rename to sql/updates/0.12/06397_mangos_creature_template.sql diff --git a/sql/updates/06398_mangos_creature_template.sql b/sql/updates/0.12/06398_mangos_creature_template.sql similarity index 100% rename from sql/updates/06398_mangos_creature_template.sql rename to sql/updates/0.12/06398_mangos_creature_template.sql diff --git a/sql/updates/06412_characters_declinedname.sql b/sql/updates/0.12/06412_characters_declinedname.sql similarity index 100% rename from sql/updates/06412_characters_declinedname.sql rename to sql/updates/0.12/06412_characters_declinedname.sql diff --git a/sql/updates/06426_mangos_locales.sql b/sql/updates/0.12/06426_mangos_locales.sql similarity index 100% rename from sql/updates/06426_mangos_locales.sql rename to sql/updates/0.12/06426_mangos_locales.sql diff --git a/sql/updates/06426_realmd_localization.sql b/sql/updates/0.12/06426_realmd_localization.sql similarity index 100% rename from sql/updates/06426_realmd_localization.sql rename to sql/updates/0.12/06426_realmd_localization.sql diff --git a/sql/updates/06431_mangos_mangos_string.sql b/sql/updates/0.12/06431_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06431_mangos_mangos_string.sql rename to sql/updates/0.12/06431_mangos_mangos_string.sql diff --git a/sql/updates/06439_mangos_command.sql b/sql/updates/0.12/06439_mangos_command.sql similarity index 100% rename from sql/updates/06439_mangos_command.sql rename to sql/updates/0.12/06439_mangos_command.sql diff --git a/sql/updates/06456_mangos_command.sql b/sql/updates/0.12/06456_mangos_command.sql similarity index 100% rename from sql/updates/06456_mangos_command.sql rename to sql/updates/0.12/06456_mangos_command.sql diff --git a/sql/updates/06472_realmd_account.sql b/sql/updates/0.12/06472_realmd_account.sql similarity index 100% rename from sql/updates/06472_realmd_account.sql rename to sql/updates/0.12/06472_realmd_account.sql diff --git a/sql/updates/06492_mangos_spell_chain.sql b/sql/updates/0.12/06492_mangos_spell_chain.sql similarity index 100% rename from sql/updates/06492_mangos_spell_chain.sql rename to sql/updates/0.12/06492_mangos_spell_chain.sql diff --git a/sql/updates/06496_mangos_spell_pet_auras.sql b/sql/updates/0.12/06496_mangos_spell_pet_auras.sql similarity index 100% rename from sql/updates/06496_mangos_spell_pet_auras.sql rename to sql/updates/0.12/06496_mangos_spell_pet_auras.sql diff --git a/sql/updates/06506_mangos_spell_proc_event.sql b/sql/updates/0.12/06506_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06506_mangos_spell_proc_event.sql rename to sql/updates/0.12/06506_mangos_spell_proc_event.sql diff --git a/sql/updates/06509_mangos_command.sql b/sql/updates/0.12/06509_mangos_command.sql similarity index 100% rename from sql/updates/06509_mangos_command.sql rename to sql/updates/0.12/06509_mangos_command.sql diff --git a/sql/updates/06509_mangos_mangos_string.sql b/sql/updates/0.12/06509_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06509_mangos_mangos_string.sql rename to sql/updates/0.12/06509_mangos_mangos_string.sql diff --git a/sql/updates/06513_mangos_command.sql b/sql/updates/0.12/06513_mangos_command.sql similarity index 100% rename from sql/updates/06513_mangos_command.sql rename to sql/updates/0.12/06513_mangos_command.sql diff --git a/sql/updates/06515_mangos_spell_proc_event.sql b/sql/updates/0.12/06515_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06515_mangos_spell_proc_event.sql rename to sql/updates/0.12/06515_mangos_spell_proc_event.sql diff --git a/sql/updates/06521_mangos_spell_proc_event.sql b/sql/updates/0.12/06521_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06521_mangos_spell_proc_event.sql rename to sql/updates/0.12/06521_mangos_spell_proc_event.sql diff --git a/sql/updates/06523_mangos_spell_proc_event.sql b/sql/updates/0.12/06523_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06523_mangos_spell_proc_event.sql rename to sql/updates/0.12/06523_mangos_spell_proc_event.sql diff --git a/sql/updates/06528_mangos_spell_affect.sql b/sql/updates/0.12/06528_mangos_spell_affect.sql similarity index 100% rename from sql/updates/06528_mangos_spell_affect.sql rename to sql/updates/0.12/06528_mangos_spell_affect.sql diff --git a/sql/updates/06528_mangos_spell_proc_event.sql b/sql/updates/0.12/06528_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06528_mangos_spell_proc_event.sql rename to sql/updates/0.12/06528_mangos_spell_proc_event.sql diff --git a/sql/updates/06538_mangos_spell_proc_event.sql b/sql/updates/0.12/06538_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06538_mangos_spell_proc_event.sql rename to sql/updates/0.12/06538_mangos_spell_proc_event.sql diff --git a/sql/updates/06540_mangos_spell_proc_event.sql b/sql/updates/0.12/06540_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06540_mangos_spell_proc_event.sql rename to sql/updates/0.12/06540_mangos_spell_proc_event.sql diff --git a/sql/updates/06544_mangos_spell_proc_event.sql b/sql/updates/0.12/06544_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06544_mangos_spell_proc_event.sql rename to sql/updates/0.12/06544_mangos_spell_proc_event.sql diff --git a/sql/updates/06545_mangos_command.sql b/sql/updates/0.12/06545_mangos_command.sql similarity index 100% rename from sql/updates/06545_mangos_command.sql rename to sql/updates/0.12/06545_mangos_command.sql diff --git a/sql/updates/06557_mangos_command.sql b/sql/updates/0.12/06557_mangos_command.sql similarity index 100% rename from sql/updates/06557_mangos_command.sql rename to sql/updates/0.12/06557_mangos_command.sql diff --git a/sql/updates/06574_mangos_spell_proc_event.sql b/sql/updates/0.12/06574_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06574_mangos_spell_proc_event.sql rename to sql/updates/0.12/06574_mangos_spell_proc_event.sql diff --git a/sql/updates/06585_mangos_command.sql b/sql/updates/0.12/06585_mangos_command.sql similarity index 100% rename from sql/updates/06585_mangos_command.sql rename to sql/updates/0.12/06585_mangos_command.sql diff --git a/sql/updates/06588_mangos_spell_proc_event.sql b/sql/updates/0.12/06588_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06588_mangos_spell_proc_event.sql rename to sql/updates/0.12/06588_mangos_spell_proc_event.sql diff --git a/sql/updates/06596_characters_arena_team.sql b/sql/updates/0.12/06596_characters_arena_team.sql similarity index 100% rename from sql/updates/06596_characters_arena_team.sql rename to sql/updates/0.12/06596_characters_arena_team.sql diff --git a/sql/updates/06598_character_spell.sql b/sql/updates/0.12/06598_character_spell.sql similarity index 100% rename from sql/updates/06598_character_spell.sql rename to sql/updates/0.12/06598_character_spell.sql diff --git a/sql/updates/06609_mangos_mangos_string.sql b/sql/updates/0.12/06609_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06609_mangos_mangos_string.sql rename to sql/updates/0.12/06609_mangos_mangos_string.sql diff --git a/sql/updates/06613_mangos_mangos_string.sql b/sql/updates/0.12/06613_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06613_mangos_mangos_string.sql rename to sql/updates/0.12/06613_mangos_mangos_string.sql diff --git a/sql/updates/06627_mangos_creature_movement.sql b/sql/updates/0.12/06627_mangos_creature_movement.sql similarity index 100% rename from sql/updates/06627_mangos_creature_movement.sql rename to sql/updates/0.12/06627_mangos_creature_movement.sql diff --git a/sql/updates/06640_mangos_reference_loot_template.sql b/sql/updates/0.12/06640_mangos_reference_loot_template.sql similarity index 100% rename from sql/updates/06640_mangos_reference_loot_template.sql rename to sql/updates/0.12/06640_mangos_reference_loot_template.sql diff --git a/sql/updates/06642_characters_declinedname.sql b/sql/updates/0.12/06642_characters_declinedname.sql similarity index 100% rename from sql/updates/06642_characters_declinedname.sql rename to sql/updates/0.12/06642_characters_declinedname.sql diff --git a/sql/updates/06668_mangos_spell_proc_event.sql b/sql/updates/0.12/06668_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06668_mangos_spell_proc_event.sql rename to sql/updates/0.12/06668_mangos_spell_proc_event.sql diff --git a/sql/updates/06673_mangos_areatrigger_scripts.sql b/sql/updates/0.12/06673_mangos_areatrigger_scripts.sql similarity index 100% rename from sql/updates/06673_mangos_areatrigger_scripts.sql rename to sql/updates/0.12/06673_mangos_areatrigger_scripts.sql diff --git a/sql/updates/06676_mangos_spell_proc_event.sql b/sql/updates/0.12/06676_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06676_mangos_spell_proc_event.sql rename to sql/updates/0.12/06676_mangos_spell_proc_event.sql diff --git a/sql/updates/06681_mangos_mangos_string.sql b/sql/updates/0.12/06681_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06681_mangos_mangos_string.sql rename to sql/updates/0.12/06681_mangos_mangos_string.sql diff --git a/sql/updates/06691_mangos_spell_proc_event.sql b/sql/updates/0.12/06691_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06691_mangos_spell_proc_event.sql rename to sql/updates/0.12/06691_mangos_spell_proc_event.sql diff --git a/sql/updates/06693_mangos_spell_affect.sql b/sql/updates/0.12/06693_mangos_spell_affect.sql similarity index 100% rename from sql/updates/06693_mangos_spell_affect.sql rename to sql/updates/0.12/06693_mangos_spell_affect.sql diff --git a/sql/updates/06693_mangos_spell_proc_event.sql b/sql/updates/0.12/06693_mangos_spell_proc_event.sql similarity index 100% rename from sql/updates/06693_mangos_spell_proc_event.sql rename to sql/updates/0.12/06693_mangos_spell_proc_event.sql diff --git a/sql/updates/06698_characters_character_tutorial.sql b/sql/updates/0.12/06698_characters_character_tutorial.sql similarity index 100% rename from sql/updates/06698_characters_character_tutorial.sql rename to sql/updates/0.12/06698_characters_character_tutorial.sql diff --git a/sql/updates/06701_mangos_command.sql b/sql/updates/0.12/06701_mangos_command.sql similarity index 100% rename from sql/updates/06701_mangos_command.sql rename to sql/updates/0.12/06701_mangos_command.sql diff --git a/sql/updates/06701_mangos_mangos_string.sql b/sql/updates/0.12/06701_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06701_mangos_mangos_string.sql rename to sql/updates/0.12/06701_mangos_mangos_string.sql diff --git a/sql/updates/06708_mangos_mangos_string.sql b/sql/updates/0.12/06708_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06708_mangos_mangos_string.sql rename to sql/updates/0.12/06708_mangos_mangos_string.sql diff --git a/sql/updates/06715_mangos_spell_affect.sql b/sql/updates/0.12/06715_mangos_spell_affect.sql similarity index 100% rename from sql/updates/06715_mangos_spell_affect.sql rename to sql/updates/0.12/06715_mangos_spell_affect.sql diff --git a/sql/updates/06728_mangos_quest_template.sql b/sql/updates/0.12/06728_mangos_quest_template.sql similarity index 100% rename from sql/updates/06728_mangos_quest_template.sql rename to sql/updates/0.12/06728_mangos_quest_template.sql diff --git a/sql/updates/06730_mangos_mangos_string.sql b/sql/updates/0.12/06730_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06730_mangos_mangos_string.sql rename to sql/updates/0.12/06730_mangos_mangos_string.sql diff --git a/sql/updates/06740_characters_characters.sql b/sql/updates/0.12/06740_characters_characters.sql similarity index 100% rename from sql/updates/06740_characters_characters.sql rename to sql/updates/0.12/06740_characters_characters.sql diff --git a/sql/updates/06740_mangos_command.sql b/sql/updates/0.12/06740_mangos_command.sql similarity index 100% rename from sql/updates/06740_mangos_command.sql rename to sql/updates/0.12/06740_mangos_command.sql diff --git a/sql/updates/06740_mangos_mangos_string.sql b/sql/updates/0.12/06740_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06740_mangos_mangos_string.sql rename to sql/updates/0.12/06740_mangos_mangos_string.sql diff --git a/sql/updates/06742_mangos_command.sql b/sql/updates/0.12/06742_mangos_command.sql similarity index 100% rename from sql/updates/06742_mangos_command.sql rename to sql/updates/0.12/06742_mangos_command.sql diff --git a/sql/updates/06742_mangos_mangos_string.sql b/sql/updates/0.12/06742_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06742_mangos_mangos_string.sql rename to sql/updates/0.12/06742_mangos_mangos_string.sql diff --git a/sql/updates/06748_mangos_mangos_string.sql b/sql/updates/0.12/06748_mangos_mangos_string.sql similarity index 100% rename from sql/updates/06748_mangos_mangos_string.sql rename to sql/updates/0.12/06748_mangos_mangos_string.sql diff --git a/sql/updates/06750_mangos_command.sql b/sql/updates/0.12/06750_mangos_command.sql similarity index 100% rename from sql/updates/06750_mangos_command.sql rename to sql/updates/0.12/06750_mangos_command.sql diff --git a/sql/updates/06751_realmd_account.sql b/sql/updates/0.12/06751_realmd_account.sql similarity index 100% rename from sql/updates/06751_realmd_account.sql rename to sql/updates/0.12/06751_realmd_account.sql diff --git a/sql/updates/06760_mangos_creature_template.sql b/sql/updates/0.12/06760_mangos_creature_template.sql similarity index 100% rename from sql/updates/06760_mangos_creature_template.sql rename to sql/updates/0.12/06760_mangos_creature_template.sql diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index 33d0db725..f0f5f2d09 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -25,73 +25,6 @@ pkgdatadir = $(datadir)/mangos/sql/updates ## Files to be installed # Install basic SQL files to datadir pkgdata_DATA = \ - 06360_characters_corpse.sql \ - 06360_characters_characters.sql \ - 06362_characters.sql \ - 06362_mangos_instance_template.sql \ - 06367_mangos_spell_proc_event.sql \ - 06369_mangos_spell_affect.sql \ - 06370_mangos_spell_affect.sql \ - 06381_mangos_command.sql \ - 06387_characters_character_ticket.sql \ - 06387_mangos_mangos_string.sql \ - 06397_mangos_creature_template.sql \ - 06398_mangos_creature_template.sql \ - 06412_characters_declinedname.sql \ - 06426_mangos_locales.sql \ - 06426_realmd_localization.sql \ - 06431_mangos_mangos_string.sql \ - 06439_mangos_command.sql \ - 06456_mangos_command.sql \ - 06472_realmd_account.sql \ - 06492_mangos_spell_chain.sql \ - 06496_mangos_spell_pet_auras.sql \ - 06506_mangos_spell_proc_event.sql \ - 06509_mangos_command.sql \ - 06509_mangos_mangos_string.sql \ - 06513_mangos_command.sql \ - 06515_mangos_spell_proc_event.sql \ - 06521_mangos_spell_proc_event.sql \ - 06523_mangos_spell_proc_event.sql \ - 06528_mangos_spell_affect.sql \ - 06528_mangos_spell_proc_event.sql \ - 06538_mangos_spell_proc_event.sql \ - 06540_mangos_spell_proc_event.sql \ - 06544_mangos_spell_proc_event.sql \ - 06545_mangos_command.sql \ - 06557_mangos_command.sql \ - 06574_mangos_spell_proc_event.sql \ - 06585_mangos_command.sql \ - 06588_mangos_spell_proc_event.sql \ - 06596_characters_arena_team.sql \ - 06598_character_spell.sql \ - 06609_mangos_mangos_string.sql \ - 06613_mangos_mangos_string.sql \ - 06627_mangos_creature_movement.sql \ - 06640_mangos_reference_loot_template.sql \ - 06642_characters_declinedname.sql \ - 06668_mangos_spell_proc_event.sql \ - 06676_mangos_spell_proc_event.sql \ - 06681_mangos_mangos_string.sql \ - 06691_mangos_spell_proc_event.sql \ - 06693_mangos_spell_affect.sql \ - 06693_mangos_spell_proc_event.sql \ - 06698_characters_character_tutorial.sql \ - 06701_mangos_command.sql \ - 06701_mangos_mangos_string.sql \ - 06708_mangos_mangos_string.sql \ - 06715_mangos_spell_affect.sql \ - 06728_mangos_quest_template.sql \ - 06730_mangos_mangos_string.sql \ - 06740_characters_characters.sql \ - 06740_mangos_command.sql \ - 06740_mangos_mangos_string.sql \ - 06742_mangos_command.sql \ - 06742_mangos_mangos_string.sql \ - 06748_mangos_mangos_string.sql \ - 06750_mangos_command.sql \ - 06751_realmd_account.sql \ - 06760_mangos_creature_template.sql \ 2008_10_18_01_characters_characters.sql \ 2008_10_18_02_mangos_spell_proc_event.sql \ 2008_10_19_01_mangos_spell_affect.sql \ @@ -167,74 +100,6 @@ pkgdata_DATA = \ ## Additional files to include when running 'make dist' # SQL update files, to upgrade database schema from older revisions EXTRA_DIST = \ - 06360_characters_corpse.sql \ - 06360_characters_characters.sql \ - 06362_characters.sql \ - 06362_mangos_instance_template.sql \ - 06367_mangos_spell_proc_event.sql \ - 06369_mangos_spell_affect.sql \ - 06370_mangos_spell_affect.sql \ - 06381_mangos_command.sql \ - 06387_characters_character_ticket.sql \ - 06387_mangos_mangos_string.sql \ - 06397_mangos_creature_template.sql \ - 06398_mangos_creature_template.sql \ - 06412_characters_declinedname.sql \ - 06426_mangos_locales.sql \ - 06426_realmd_localization.sql \ - 06431_mangos_mangos_string.sql \ - 06439_mangos_command.sql \ - 06456_mangos_command.sql \ - 06472_realmd_account.sql \ - 06492_mangos_spell_chain.sql \ - 06496_mangos_spell_pet_auras.sql \ - 06506_mangos_spell_proc_event.sql \ - 06509_mangos_command.sql \ - 06509_mangos_mangos_string.sql \ - 06513_mangos_command.sql \ - 06515_mangos_spell_proc_event.sql \ - 06521_mangos_spell_proc_event.sql \ - 06523_mangos_spell_proc_event.sql \ - 06528_mangos_spell_affect.sql \ - 06528_mangos_spell_proc_event.sql \ - 06538_mangos_spell_proc_event.sql \ - 06540_mangos_spell_proc_event.sql \ - 06544_mangos_spell_proc_event.sql \ - 06545_mangos_command.sql \ - 06557_mangos_command.sql \ - 06574_mangos_spell_proc_event.sql \ - 06585_mangos_command.sql \ - 06588_mangos_spell_proc_event.sql \ - 06596_characters_arena_team.sql \ - 06598_character_spell.sql \ - 06609_mangos_mangos_string.sql \ - 06613_mangos_mangos_string.sql \ - 06627_mangos_creature_movement.sql \ - 06640_mangos_reference_loot_template.sql \ - 06642_characters_declinedname.sql \ - 06668_mangos_spell_proc_event.sql \ - 06673_mangos_areatrigger_scripts.sql \ - 06676_mangos_spell_proc_event.sql \ - 06681_mangos_mangos_string.sql \ - 06691_mangos_spell_proc_event.sql \ - 06693_mangos_spell_affect.sql \ - 06693_mangos_spell_proc_event.sql \ - 06698_characters_character_tutorial.sql \ - 06701_mangos_command.sql \ - 06701_mangos_mangos_string.sql \ - 06708_mangos_mangos_string.sql \ - 06715_mangos_spell_affect.sql \ - 06728_mangos_quest_template.sql \ - 06730_mangos_mangos_string.sql \ - 06740_characters_characters.sql \ - 06740_mangos_command.sql \ - 06740_mangos_mangos_string.sql \ - 06742_mangos_command.sql \ - 06742_mangos_mangos_string.sql \ - 06748_mangos_mangos_string.sql \ - 06750_mangos_command.sql \ - 06751_realmd_account.sql \ - 06760_mangos_creature_template.sql \ 2008_10_18_01_characters_characters.sql \ 2008_10_18_02_mangos_spell_proc_event.sql \ 2008_10_19_01_mangos_spell_affect.sql \ diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index e2d3ae451..459986d45 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6931" + #define REVISION_NR "6932" #endif // __REVISION_NR_H__ From 513255585fd051317316ee06311f59383a333b55 Mon Sep 17 00:00:00 2001 From: arrai Date: Sat, 20 Dec 2008 14:17:03 +0100 Subject: [PATCH 256/256] [6933] Fixed resurrected players being attacked by creatures near their corpse although they were revived in a safe distance --- src/game/Player.cpp | 5 +++-- src/shared/revision_nr.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 0b1a5b8f2..75deff417 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -18597,6 +18597,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) @@ -18614,8 +18617,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) diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 459986d45..bbb53a827 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "6932" + #define REVISION_NR "6933" #endif // __REVISION_NR_H__